题目:http://www.acm.uestc.edu.cn/problem.php?pid=1081
/*经过多方求助和不懈努力,这个题目终于被我做出来了。 其实并不复杂的,只是对于字符串的处理把握自己在能力上还是不足的。 注意几点:RunID才是题目的提交顺序,如果 6855_Tommy_Wrong Answer_1038.cc 7036_2910201009_Compile Error_1038.cc 6915_Tommy_Accepted_1038.cc 这样的话对于Tommy来说6915才是1038题的第一次提交所以100分而不是95分*/ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; struct node { char AuthorID[51]; char RunID[10]; int Result; int Number; int Total; }stu[2005]; int T,i,j,id,start,end; char key; char s[100],RunID[10]; void input() { //printf("hehe"); gets(s); int len = strlen(s); i=len-1; while(s[i]!='.') i--; //得到.的位置,从而得到题号 id = 0; //得到题号 id+=s[i-1]-'0'; id+=(s[i-2]-'0')*10; id+=(s[i-3]-'0')*100; id+=(s[i-4]-'0')*1000; j =i-6; //得到判决结果 while(s[j]!='_')j--; key = s[j+1]; switch(key) { case 'A': stu[T].Result = 1; break; case 'P': stu[T].Result = 2; break; case 'W': stu[T].Result = 3; break; case 'C': stu[T].Result = 4; break; } end = j-1; //得到AuthorID的最后一个字符位置 i=0; while(s[i]!='_') { RunID[i] = s[i]; i++; } RunID[i] = '\0'; start = i+1; //得到Authorid的开始字符位置 char ss[55]; for(j=0,i=start;i<=end;i++,j++) ss[j]=s[i]; ss[j]='\0';//加入‘/0’是必须的 strcpy(stu[T].AuthorID,ss); stu[T].Number = id; //printf("%d ",stu[T].Result); strcpy(stu[T].RunID,RunID); } bool cmp(node a,node b) { if(strcmp(a.AuthorID,b.AuthorID)<0|| (strcmp(a.AuthorID,b.AuthorID)==0&&a.Number<b.Number)|| (strcmp(a.AuthorID,b.AuthorID)==0&&a.Number==b.Number&&strcmp(a.RunID,b.RunID)<0)) return 1; else return 0; } int main() { //freopen("1.txt","r",stdin); scanf("%d",&T); getchar(); int M = T; T = 1; while(T<=M) { input(); T++; } sort(stu+1,stu+M+1,cmp); //for(i=1;i<=M;i++) //cout<<stu[i].AuthorID<<" "<<stu[i].Number<<" "<<stu[i].Result<<endl; int s = 1,t,ss,tt,k; while(s<=M) { for(t=s+1;t<=M&&strcmp(stu[t].AuthorID,stu[s].AuthorID)==0;t++); ss = s; //ss标记的是一个人的起点 while(ss<t) //这是同一个人的范围 t-1表示的是一个人的终点 { for(tt=ss+1;tt<t&&(stu[tt].Number == stu[ss].Number);tt++);//这是单个题目的范围 ss表示一个题目的起点 tt-1表示终点 if(stu[ss].Result == 1) stu[s].Total+=100; //这是问题的关键 else { k = stu[ss].Result; //printf("%d %d %d \n",k,ss,tt); for(j=ss+1;j<tt;j++) { if(stu[j].Result<k) k = stu[j].Result; // cout<<"heeh"; } //printf("%d %d %d \n",k,ss,t); switch(k) { case 1: stu[s].Total+=95; break; case 2: stu[s].Total+=90; break; case 3: stu[s].Total+=70; break; case 4: stu[s].Total+=50; break; } } ss = tt;//跳到下一个范围 } s = t; // 跳到下一个人 //printf("%d ",s); } for(i=1;i<=M;i++) { if(stu[i].Total>0) printf("%s %d\n",stu[i].AuthorID,stu[i].Total); } return 0; }
下面是我写错了的代码,以作留念
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { char name[55];//auther id int score[6];//每个题目对应的得分 int ex[8];//用于记录是否是第一次提交 }stu[2005]; int T,index1,flag; char s[2000]; void init() //初始化 { for(int i =0;i<T;i++) { memset(stu[i].ex,0,sizeof(stu[i].ex)); memset(stu[i].score,0,sizeof(stu[i].score)); } } int search(struct node stu[],char *tok)//查找已有数据中是否有此id 有的话返回i没有的话index1+1 { for( int i=0;i<=index1;i++) { if(strcmp(tok,stu[i].name)==0) { flag = 0; return i; } } flag = 1; return index1+1; } int swap(char *p)//将字符串类型的题目编号转换为int { int sum = 0; int i=0; int beilv; while(i!=4) { if(i==0) beilv = 1000; else if(i==1) beilv =100; else if(i==2) beilv = 10; else beilv = 1; sum+=beilv*(*(p+i)-'0'); i++; } return sum; } bool cmp(const node a,const node b)//比较函数 { if(a.name<b.name) return true; else return false; } void output()//输出函数 { for(int i=0;i<=index1;i++) { int sum = 0; for(int j =0;j<6;j++) { sum+=stu[i].score[j]; } printf("%s ",stu[i].name); printf("%d\n",sum); } } int main() { freopen("1.txt","r",stdin); scanf("%d",&T); getchar(); index1=-1; init(); while(T--) { gets(s); char *tok = strtok(s,"_."); int temp; int a = 0; int id; while(tok!=NULL) { if(a==1)//如果是第二个字符串 { temp = search(stu,tok); if(flag) { strcpy(stu[temp].name,tok); } } if(a==2)//如果是第三个字符串 { char *exeID = strtok(NULL,"_."); id = swap(exeID); switch(*tok) { case 'A': if(stu[temp].ex[id-1038]==0) stu[temp].score[id-1038] = 100; else stu[temp].score[id-1038] = 95; break; case 'P': if(stu[temp].score[id-1038]<90) { stu[temp].score[id-1038] = 90; stu[temp].ex[id-1038] = 1; } break; case 'W': if(stu[temp].score[id-1038]<70) { stu[temp].score[id-1038] = 70; stu[temp].ex[id-1038] = 1; } break; case 'C': if(stu[temp].score[id-1038]<50) { stu[temp].score[id-1038] = 50; stu[temp].ex[id-1038] = 1; } break; } } tok = strtok(NULL,"_."); a++; } if(flag) index1++; } sort(stu,stu+index1+1,cmp);//按照字符排序 output(); return 0; }
就会出现悲剧的错误,于是乎本题就不能用strtok函数了
要自己亲手处理字符串了,下面是处理的悲剧过程
首先给出介绍substr函数的介绍
#include <iostream> #include <string> using namespace std; int main () { string str="We think in generalities, but we live in details."; // (quoting Alfred N. Whitehead) string str2 = str.substr (12,12); // "generalities" unsigned pos = str.find("live"); // position of "live" in str string str3 = str.substr (pos); // get from "live" to the end cout << str2 << endl<< str3 << '\n'; return 0; }
截取(包括start,并且字符串是从0开始计数的)。
当只有一个地址的时候,表示从改地址直到结束
另外例程中使用了string类的find方法
find方法的返回值是字符串的左边第一个开头字符的位置
#include <iostream> using namespace std; int main() { char a[100] = "Welcome to UESTC!"; string s =a; unsigned int b = s.find("to"); cout <<s.substr(b)<< endl; return 0; }
花了半天时间写了下面的代码
解决了上面的bug不过还是wa
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; struct node { char name[55];//auther id int score[6];//每个题目对应的得分 int ex[6];//用于记录是否是第一次提交 }stu[2005]; int T,index1,flag; char s[2000]; void init() //初始化 { for(int i =0;i<T;i++) { //memset(stu[i].ex,0,sizeof(stu[i].ex)); //memset(stu[i].score,0,sizeof(stu[i].score)); stu[i].ex[0]=0; stu[i].ex[1]=0; stu[i].ex[2]=0; stu[i].ex[3]=0; stu[i].ex[4]=0; stu[i].ex[5]=0; stu[i].score[0]=0; stu[i].score[1]=0; stu[i].score[2]=0; stu[i].score[3]=0; stu[i].score[4]=0; stu[i].score[5]=0; } } int search(struct node stu[],char tok[]) { for( int i=0;i<=index1;i++) { if(strcmp(tok,stu[i].name)==0) { flag = 0; return i; } } flag = 1; return index1+1; } bool cmp(const node a,const node b) { if(strcmp(a.name,b.name)<=0) return true; else return false; } void output() { for(int i=0;i<=index1;i++) { int sum = 0; for(int j =0;j<6;j++) { sum+=stu[i].score[j]; } printf("%s ",stu[i].name); printf("%d\n",sum); } //printf("\n"); } int main() { freopen("1.txt","r",stdin); int i,j,id,start,end,temp; char key; scanf("%d",&T); getchar(); index1=-1; init(); while(T--) { gets(s); int len = strlen(s); i=len-1; while(s[i]!='.') i--; id = 0; id+=s[i-1]-'0'; id+=(s[i-2]-'0')*10; id+=(s[i-3]-'0')*100; id+=(s[i-4]-'0')*1000; j =i-6; while(s[j]!='_')j--; key = s[j+1]; end = j-1; i=0; while(s[i]!='_') i++; start = i+1; char ss[55]; for(j=0,i=start;i<=end;i++,j++) ss[j]=s[i]; ss[j]='\0'; temp = search(stu,ss); if(flag) strcpy(stu[temp].name,ss); switch(key) { case 'A': if(stu[temp].ex[id-1038]==0) stu[temp].score[id-1038] = 100; else stu[temp].score[id-1038] = 95; stu[temp].ex[id-1038] = 1; break; case 'P': if(stu[temp].score[id-1038]<90) { stu[temp].score[id-1038] = 90; stu[temp].ex[id-1038] = 1; } break; case 'W': if(stu[temp].score[id-1038]<70) { stu[temp].score[id-1038] = 70; stu[temp].ex[id-1038] = 1; } break; case 'C': if(stu[temp].score[id-1038]<50) { stu[temp].score[id-1038] = 50; stu[temp].ex[id-1038] = 1; } break; } if(flag) index1++; } sort(stu,stu+index1+1,cmp);//按照字符排序 output(); return 0; }
经过分析求证询问找出另一个问题,这个问题存在于题目本身,题目本身就是又bug的
题目的真是意图是RunID也是有用处的,我默认给出数据的顺序就是提交的顺序(事实上从题目表面意思来看就是这个意思的)
而事实上不是的RunID才是真正的提交顺序,因此还要对RunID进行排序
在书写过程中又发现了一个问题
C++的string类型是可以直接通过> < 来进行比较的,但是char [] 字符串只能通过字符串比较函数strcmp来进行比较
各种纠结哈!求解救!
switch()
case 1: 呵呵