http://ac.jobdu.com/problem.php?pid=1029魔咒词典
题目当中每个魔咒用一对括号[ ] 来包含,测试数据在一对括号当中会有空格,这个小问题导致一直是WA,应该首先把一行字符串都读进来,然后在分别提取出魔咒和对应的功能。
方法一:
//使用双map来实现 #include<iostream> #include<map> #include<cstdio> #include<string> using namespace std; map<string,string>map_magic,map_funtion; int main(void) { int n,k; string str1,str2,str,temp_str; map_magic.clear(); map_funtion.clear(); while(getline(cin,temp_str)) { if(temp_str=="@END@") break; k=temp_str.find("]"); str1=temp_str.substr(0,k+1); str2=temp_str.substr(k+2,temp_str.size()-k-2); map_magic[str1]=str2; map_funtion[str2]=str1; } scanf("%d",&n); getchar(); while(n--) { getline(cin,str); if(str[0]=='[') { if(map_magic.count(str)) cout<<map_magic[str]<<endl; //由魔咒来选择功能 else cout<<"what?"<<endl; } else { if(map_funtion.count(str)) { temp_str=map_funtion[str]; //由功能来选择魔咒 cout<<temp_str.substr(1,temp_str.size()-2)<<endl; } else cout<<"what?"<<endl; } } return 0; }
方法二:
//字符串哈希的时间最快,只需要10 MS #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define N 100100 #define M 100100 const char *end = "@END@"; char word[N][25], expr[N][85]; int magic[M], funtion[M]; unsigned int bkdrHash(char *str) { unsigned int seed = 131; unsigned int hash = 0; while(*str) { hash = hash * seed + *str++; } return (hash & 0x7FFFFFFF) % M; } int setPos(int idx, int arr[]) { int i = 1; while(arr[idx]) //哈希地址冲突的时候 { idx = (idx + i * i) % M; //处理哈希冲突的方法,二次探测再散列 i++; } return idx; } int getPos(int idx, int arr[], int type, char *str) { int i = 1, k = 0; while(arr[idx]) { if(type == 0 && strcmp(word[arr[idx]], str) == 0) { k = magic[idx]; //找到魔咒在字典中的位置 break; } else if(type && strcmp(expr[arr[idx]], str) == 0) { k = funtion[idx]; //找到功能在字典中的位置 break; } else { idx = (idx + i * i) % M; i++; } } return k; } int main(void) { char str[128]; int i, j, k, n; k = 1; memset(magic, 0, sizeof(magic)); memset(funtion, 0, sizeof(funtion)); while(gets(str)) { if(strcmp(str, end) == 0) break; for(i=0;str[i]!= ']';i++) word[k][i]=str[i]; //保存魔咒 word[k][i]=str[i]; i++; word[k][i++]='\0'; j = setPos(bkdrHash(word[k]), magic); magic[j] = k; j = 0; for(;str[i]!='\0';i++) expr[k][j++]=str[i]; //保存功能 expr[k][j]='\0'; j = setPos(bkdrHash(expr[k]), funtion); funtion[j] = k; k++; } scanf("%d", &n); getchar(); while(n--) { gets(str); if(str[0] == '[') { j = getPos(bkdrHash(str), magic, 0, str); if(j) //查询成功 puts(expr[j]); else //查询失败 printf("what?\n"); } else { j = getPos(bkdrHash(str), funtion, 1, str); if(j) { k = strlen(word[j]); for(i = 1; i < k-1; i++) printf("%c", word[j][i]); printf("\n"); } else printf("what?\n"); } } return 0; }方法三:
//二分查找 #include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<string> using namespace std; struct Word { string magic; string funtion; }word; vector<Word> dic1,dic2; int my_binary_search(int low, int high,string key,int i) { int mid; if(i==1) //查找魔咒 { while(low<=high) { mid=(low+high)>>1; if(key<dic1[mid].magic) high=mid-1; else if(key==dic1[mid].magic) return mid; else low=mid+1; } } else if(i==2) //查找功能 { while(low<=high) { mid=(low+high)>>1; if(key<dic2[mid].funtion) high=mid-1; else if(key==dic2[mid].funtion) return mid; else low=mid+1; } } return -1; //查找失败 } bool cmp1(const Word &a,const Word &b) { return a.magic<b.magic; } bool cmp2(const Word &a,const Word &b) { return a.funtion<b.funtion; } int main(void) { int n,k; string str,temp_str; while(getline(cin,temp_str)) { if(temp_str=="@END@") break; k=temp_str.find("]"); word.magic=temp_str.substr(0,k+1); word.funtion=temp_str.substr(k+2,temp_str.size()-k-2); dic1.push_back(word); dic2.push_back(word); } sort(dic1.begin(), dic1.end(), cmp1); //按照魔咒的字典序进行排序 sort(dic2.begin(), dic2.end(), cmp2); //按照功能的字典序进行排序 scanf("%d",&n); getchar(); vector<Word>::iterator iter; //vector的迭代器 while(n--) { getline(cin,str); if(str[0]=='[') //由魔咒来选择功能 { k=my_binary_search(0, dic1.size()-1,str,1); if(k!=-1) cout<<dic1[k].funtion<<endl; else cout<<"what?"<<endl; } else { k=my_binary_search(0, dic2.size()-1 ,str,2); if(k!=-1) { temp_str=dic2[k].magic; cout<<temp_str.substr(1,temp_str.size()-2)<<endl; } else cout<<"what?"<<endl; } } return 0; }
方法四: (可能会导致超时)
//使用一个map来实现,反过来用迭代器查询 #include<iostream> #include<map> #include<cstdio> #include<string> using namespace std; map<string,string>map_magic; int main(void) { int n,k; string str1,str2,str,temp_str; map_magic.clear(); while(getline(cin,temp_str)) { if(temp_str=="@END@") break; k=temp_str.find("]"); str1=temp_str.substr(0,k+1); str2=temp_str.substr(k+2,temp_str.size()-k-2); map_magic[str1]=str2; } scanf("%d",&n); getchar(); map<string,string>::iterator iter; //map的迭代器 while(n--) { getline(cin,str); if(str[0]=='[') { if(map_magic.count(str)) cout<<map_magic[str]<<endl; //由魔咒来选择功能 else cout<<"what?"<<endl; } else { for(iter=map_magic.begin();iter!=map_magic.end();iter++) { if((*iter).second==str) { temp_str=(*iter).first; cout<<temp_str.substr(1,temp_str.size()-2)<<endl; break; } } if(iter==map_magic.end()) cout<<"what?"<<endl; } } return 0; }
http://ac.jobdu.com/problem.php?id=1030 毕业bg
/* 题目实质是01背包问题,不过加了几方面的限制 将bg当作物品,离开时间当作重量,快乐度当作价值,则与01背包不同的是物品放入的顺序是有先后顺序的 所以需要排序 */ #include<iostream> #include<algorithm> #include<cstdio> using namespace std; #include<memory.h> struct Node { int happy; int last; int time; }node[31]; bool cmp(const Node &a,const Node &b) { return a.time<b.time; } int dp[1000]; int ZeroOnePack(int n) { int i,j,max=-1,p; memset(dp,0,sizeof(dp)); for(i=0;i<n;i++) //动态规划 { if(node[i].time>max) max=node[i].time; for(j=node[i].time;j>=node[i].last;j--) //j表示背包的大小,从最后离开的时间到持续时间 dp[j] = dp[j]>dp[j-node[i].last]+node[i].happy? dp[j]:dp[j-node[i].last]+node[i].happy; } p=-1; for(i=1;i<=max;i++) { if(dp[i]>p) p=dp[i]; } return p; } int main(void) { int i,n; while(scanf("%d",&n)!=EOF) { if(n<0) break; for(i=0;i<n;i++) scanf("%d %d %d",&node[i].happy,&node[i].last,&node[i].time); sort(node,node+n,cmp); //按最后离开的时间从小到大排序 printf("%d\n",ZeroOnePack(n)); } return 0; }