BestCoder Round #92 1001 Skip the Class —— 字典树 or map容器

题目链接: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\n",ans);  
76     }  
77     return 0;  
78 }  
View Code

 


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\n",ans);  
31     }  
32     return 0;  
33 }  
View Code

 

posted on 2017-03-17 14:42  h_z_cong  阅读(253)  评论(0编辑  收藏  举报

导航