07年度-ACM-ICPC国内予選

2007B

  • Blue Screenの解答

回答者:七星(PLOW)
所要時間:55分
予選時:クリア/1ミス

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <conio.h>
class CData
{
public:
	CData();	
	bool Login(int, int, int);
	bool Logout(int, int);
	int Output(int , int, int);
	void Combine(CData*);
	int student;
	int PC;
	int BeginTime;
	int EndTime;
};
void CData::Combine(CData *pDat)
{
	if(EndTime == 0)
	{
		return;
	}
	if(pDat->student == student)
	{
		if(pDat->BeginTime < EndTime )
		{
			if(pDat->EndTime > EndTime)
			{
				EndTime = pDat->EndTime;
			}
			pDat->EndTime = 0;
		}
	}
}
int CData::Output(int time, int time2, int stu)
{
	int bo;
	if(EndTime <= 0)
	{
		return 0;
	}
	if(stu != student)
	{
		return 0;
	}
	if(time < BeginTime)
	{
		if(time2 > EndTime)
		{
			return (EndTime - BeginTime);
		}
		else
		{
			bo = time2 - BeginTime;
			if(bo > 0)
			{
				return bo;
			}
			return 0;
		}
	}
	else if(time2 < BeginTime || time > EndTime)
	{
		return 0;
	}
	else if(time > BeginTime && time2 < EndTime)
	{
		return (time2 - time);
	}
	else
	{
		if(time2 > EndTime)
		{
			return (EndTime - time);
		}
		else
		{
			bo = EndTime - time;
			if(bo > 0)
			{
				return bo;
			}
			return 0;
		}
	}
	return 0;
}
CData::CData()
{
	memset(this, 0, sizeof(CData));
	PC = -1;
}
bool CData::Login(int time, int pc, int stu)
{
	if(BeginTime != 0)
	{
		return false;
	}
	PC = pc;
	BeginTime = time;
	student = stu;
	return true;
}
bool CData::Logout(int time, int pc)
{
	if(EndTime != 0)
	{
		return false;
	}
	if(PC == pc)
	{
		EndTime = time;
		return true;
	}
	return false;
}
int main()
{
	//ファイル処理-----------------
	char FileName[256];
	printf("ファイル名を入れて〜");
	scanf("%256s", FileName);
	FILE* fpIn = fopen(FileName, "r");
	FILE* fpOut = fopen("output.txt", "w");
	//-----------------------------
	int PCNum, StuNum, DatNum;
	int Time, PC, Student, bo, QNum, total;
	CData* pDat;
	while(1)
	{
		fscanf(fpIn, "%d %d", &PCNum, &StuNum);
		if(PCNum == 0 && StuNum == 0)
		{
			break;
		}
		fscanf(fpIn, "%d", &DatNum);
		//データ読み込み
		pDat = new CData[DatNum];
		for(int i = 0; i < DatNum;i++)
		{
			fscanf(fpIn,"%d %d %d %d", &Time, &PC, &Student, &bo);
			if(bo)
			{
				for(int k = 0;k < DatNum;k++)
				{
					if(pDat[k].Login(Time, PC, Student))
					{
						break;
					}
				}
			}
			else
			{
				for(int k = 0;k < DatNum;k++)
				{
					if(pDat[k].Logout(Time, PC))
					{
						break;
					}
				}
			}
		}
		//質問処理
		for(int i = 0;i < DatNum;i++)
		{
			for(int k = i + 1;k < DatNum;k++)
			{
				pDat[i].Combine(&pDat[k]);
			}
		}
		fscanf(fpIn,"%d", &QNum);
		for(int i = 0;i < QNum;i++)
		{
			fscanf(fpIn,"%d %d %d", &Time, &PC, &Student);
			total = 0;
			for(int k = 0;k < DatNum;k++)
			{
				total += pDat[k].Output(Time, PC, Student);
			}
			fprintf(fpOut, "%d\n", total);
		}
		delete [] pDat;
	}
	//終了処理---------------------
	fclose(fpOut);
	printf("終了!");
	getch();
	return 0;
}
  • 解説
    CDataクラスを作成し各PCの使用記録を保存してから、
    同じ生徒が複数のPCを重なる時間帯に使用していた場合は1つのデータに結合する事で
    各生徒の連続使用毎の使用記録にした。
    その後、このCDataから各質問に対応する結果を出力させた。

    出力の際の場合分けが若干複雑。
  • include studioの解答
    回答者:CISC
    所要時間:160分+20分
    予選時:ドボン
#include <stdio.h>

FILE *fp_in, *fp_out;
static char *f_source = "B_in.txt";
static char *f_answer = "B_out.txt";

struct DATA{
    int t,n,m,s;
};

int main(void)
{
   int maxStu,maxPC,maxData,maxQue,time;
   struct DATA data[1001];
   int qts,qte,qm;
   int i,j,k;
   int cntLogIn,logInTime;
   
   fp_in = fopen(f_source, "r");
   fp_out = fopen(f_answer, "w");
   while(1)
   {
       fscanf(fp_in, "%d %d ",&maxPC,&maxStu);
       
       //終了条件確認
       if(maxPC==0 && maxStu==0) break;
       
       fscanf(fp_in, "%d ",&maxData);
       
       //利用記録読み込み
       for(i=0;i<maxData;i++)
       {
           fscanf(fp_in, "%d %d %d %d ",
                   &(data[i].t) ,&(data[i].n) ,&(data[i].m) ,&(data[i].s));
       }
       
       //質問読み込み確認
       fscanf(fp_in , "%d ",&maxQue);
       for(i=0;i<maxQue;i++)
       {
           //読み込み
           fscanf(fp_in, "%d %d %d ",
                   &(qts) ,&(qte) ,&(qm) );
           
           //確認作業
           time=0;cntLogIn=0;
           for(k=0;k<maxData;k++)
           {//利用記録から学生を検索
               if(data[k].m == qm)
               {//記録に該当する学生がいた場合
                   if(data[k].s==1)
                   {//ログインしたとき
                       if(cntLogIn==0)
                       {
                           logInTime=data[k].t;
                       }
                       cntLogIn++;
                   }
                   else
                   {//ログアウトしたとき
                       cntLogIn--;
                       if(cntLogIn==0)
                       {
                           if(qts>data[k].t || qte<logInTime)
                           {
                               ;
                           }
                           else if(qts>=logInTime && data[k].t>=qte)
                           {
                               time+=qte-qts;
                           }
                           else if(qts<=logInTime && data[k].t<=qte)
                           {
                               time+=data[k].t-logInTime;
                           }
                           else if(qts>=logInTime && data[k].t<=qte)
                           {
                               time+=data[k].t-qts;
                           }
                           else if(qts<=logInTime && data[k].t>=qte)
                           {
                               time+=qte-logInTime;
                           }
                       }
                   }
               }
           }
           fprintf(fp_out, "%d\n",time);
       }
   }
   fclose(fp_in);
   fclose(fp_out);
   return 0;
}
  • 解説(言い訳)
    B問題ごときに160分かけてしまった私です。今日20分ほどで解決しました。。
    原因は、ズバリ「問題読み間違え」です。延べ利用時間じゃなかったんですね・・・。

プログラムの解説は、まあ特に言うこともないのですが、順を追って処理し、
重複ログインはカウントの増減で判断しています。
多分それ以外には書くほどのこともないかなぁと。

ちなみに、不正なデータがあるとこいつは処理できません。


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-11-21 (木) 11:25:35 (1616d)