题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=748&pid=1001
题解:
1.trie树
关键是如何将科目与分数进行对应,即如果将字符串与数字对应。由于之前解除了字典树,所以就想到用字典树存储单词,并为每种编上编号,之后就用这个编号与分数对应。
就个人观点而言,a[][]数组应该不用清零,因为下个case会将之前的case覆盖掉,但是错了,也找不出原因。所以以后为了安全起见,不管是否会被覆盖,都清零吧,这样保险一点。
代码如下:
1 #include<bits/stdc++.h>//字典树 2 3 using namespace std; 4 5 int a[105][105],deg[105], b[105],vis[105],sum; 6 //a[][]记录单词的值,从1开始记录。deg[]记录单词有多少个值。sum为单词的种数。 7 8 typedef struct node//字典树的结点 9 { 10 struct node *next[26]; 11 int pos; 12 }Trie, *PT; 13 14 int init(PT &p)//初始化结点 15 { 16 p = (PT)malloc(sizeof(Trie)); 17 p->pos = 0; 18 for(int i = 0; i<26; i++) 19 p->next[i] = NULL; 20 } 21 22 //访问字典树,若果单词已存在,则返回这个单词的编号,如果不存在,则编号加1,并返回。 23 int trie(char *s, int k, PT &p) 24 { 25 if(!s[k]) 26 { 27 if(p->pos) return p->pos; 28 p->pos = ++sum; 29 return p->pos; 30 } 31 32 else 33 { 34 if(!p->next[s[k]-'a']) 35 init(p->next[s[k]-'a']); 36 return trie(s,k+1,p->next[s[k]-'a']); 37 } 38 } 39 40 int cmp(int a,int b) 41 { 42 return a > b; 43 } 44 45 int main() 46 { 47 int T,n,val,ans; 48 char s[15]; 49 PT p; 50 scanf("%d",&T); 51 while(T--) 52 { 53 init(p); 54 scanf("%d",&n); 55 ans = 0; sum = 0; 56 memset(deg,0,sizeof(deg)); 57 memset(vis,0,sizeof(vis)); 58 memset(a,0,sizeof(a));//为什么少了这步会出错,这步好像不是必要的吧? 59 for(int i = 0; i<n; i++) 60 { 61 scanf("%s%d",s,&val); 62 b[i] = trie(s,0,p);//获取单词的编号,并将其储存到b[]中, 63 a[b[i]][deg[b[i]]++] = val;//更新a数组和deg数组 64 } 65 66 for(int i = 0; i<n; i++) 67 { 68 if(!vis[b[i]])//如果没有访问编号为b[i]的单词,则访问。 69 { //对这个单词的值进行排序,选其前二,并标为已访问。 70 sort(a[b[i]],a[b[i]]+deg[b[i]],cmp); 71 vis[b[i]] = 1; 72 ans += a[b[i]][0] + a[b[i]][1]; 73 } 74 } 75 printf("%d ",ans); 76 } 77 return 0; 78 }
2.map容器
其实做题时想到用c++的map会很方便,只可惜没有学map的操作。也好,现在补回来了。
对于map的认识:
1.map一个key只能对应一个val,而multimap一个key能对应多个val。所以如果对map的key进行多次复制,其旧val会被新val覆盖。而multimap则插入新的val。
2.由于map一对一,所以可以直接用map[key] = val,以数组的形式直接赋值,而multimap则只能用map.insert(pair<string,int>("ss",11))进行插入赋值。
3.要访问元素要使用迭代器map<string,int>::iterator it,last; 4
4.两种map都自动根据key值进行递增排序。
代码如下:
1 #include<bits/stdc++.h> 2 #define MAX(a,b) (a>b?a:b) 3 4 using namespace std; 5 6 int main() 7 { 8 int n,val,T; 9 char s[15]; 10 map<string,int> m1,m2; 11 map<string,int>::iterator it,last; 12 scanf("%d",&T); 13 while(T--) 14 { 15 scanf("%d",&n); 16 m1.clear(); m2.clear();//清空map 17 for(int i = 0; i<n; i++) 18 { 19 scanf("%s%d",s,&val); 20 //更新第一二大值 21 m2[s] = MAX(m2[s],val); 22 if(m1[s]<m2[s]) swap(m1[s],m2[s]); 23 } 24 25 int ans = 0; 26 for(it = m1.begin(),last = m1.end(); it!=last; it++) 27 ans += it->second; 28 for(it = m2.begin(),last = m2.end(); it!=last; it++) 29 ans += it->second; 30 printf("%d ",ans); 31 } 32 return 0; 33 }