[[07年度-ACM-ICPC国内予選]] ***2007B [#z72a2ab6] -''Blue Screenの解答'' 回答者:[[七星(PLOW)]]&br; 所要時間:55分&br; 予選時:クリア/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; } --解説&br; CDataクラスを作成し各PCの使用記録を保存してから、&br; 同じ生徒が複数のPCを重なる時間帯に使用していた場合は1つのデータに結合する事で&br; 各生徒の連続使用毎の使用記録にした。&br; その後、このCDataから各質問に対応する結果を出力させた。&br; &br; 出力の際の場合分けが若干複雑。&br; -''include studioの解答''&br; 回答者:[[CISC]]&br; 所要時間:160分+20分&br; 予選時:ドボン #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,maxRiyou,maxQue,time; 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 ",&maxRiyou); fscanf(fp_in, "%d ",&maxData); //利用記録読み込み for(i=0;i<maxRiyou;i++) 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<maxRiyou;k++) 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; } --解説(言い訳)&br; B問題ごときに160分かけてしまった私です。今日20分ほどで解決しました。。&br; 原因は、ズバリ「問題読み間違え」です。延べ利用時間じゃなかったんですね・・・。&br; プログラムの解説は、まあ特に言うこともないのですが、順を追って処理し、&br; 重複ログインはカウントの増減で判断しています。&br; 多分それ以外には書くほどのこともないかなぁと。&br; ちなみに、不正なデータがあるとこいつは処理できません。&br;