/*即每个结点有多个儿子结点。。。然后单词的前缀会在树中重合,而结点的数据域随题目而变,例如这题,数据域prefixNum表示含以该结点结尾的前缀的单词的个数。那么如果你想知道树中某单词是否存在,则数据域isWord == 1表示存在以该结点结尾的单词 字典树效率高在于他只需要遍历该单词*/#include <iostream>using namespace std;struct Node{ struct Node *child[26]; int perfixNum;//表示含以该结点结尾的前缀的单词的个数};Node *root;void Init()//初始化{ root = new Node; for (int i = 0; i < 26; i++) { root->child[i] = NULL; }}//插入void Insert(char word[]){ int len = strlen(word); Node *pNode = root; for (int i = 0; i < len; i++) { if (pNode->child[word[i] - 'a'] == NULL) { //不存在该结点,则创建一个 Node *newNode = new Node; newNode->perfixNum = 1; for (int j = 0; j < 26; j++) { newNode->child[j] = NULL; } pNode->child[word[i] - 'a'] = newNode; } else { pNode->child[word[i] - 'a']->perfixNum++; } pNode = pNode->child[word[i] - 'a']; }}//查找,通过遍历该单词到该单词的结尾结点的prefixNum就是答案了int Find(char word[]){ int len = strlen(word); Node *pNode = root; int i; for (i = 0; i < len; i++) { if (pNode->child[word[i] - 'a'] != NULL) { pNode = pNode->child[word[i] - 'a']; } else { break; } } if (i == len) { return pNode->perfixNum; } else { return 0; }}int main(){ char word[15], prefixWord[15]; Init(); while (gets(word), word[0] != 0) { Insert(word); } while (gets(prefixWord) != NULL) { printf("%d\n", Find(prefixWord)); } return 0;}
Phone List
// Trie 基础模板#include <stdio.h>#include <string.h>#include <algorithm>#include <vector>#include <stack>#include <iostream>#define Max 100000#define sigma_size 10using namespace std;int ch[Max][sigma_size];bool val[Max];int cnt;char str[10002];int idx(char c){ return c-'0';}bool insert(char *s){ int i,n=strlen(s); int c,u=0; for(i=0;i<n;i++) { c=idx(s[i]); if(!ch[u][c]) { memset(ch[cnt],0,sizeof(ch[cnt])); val[cnt]=false; ch[u][c]=cnt++; } if(val[u]) return false; u=ch[u][c]; } val[u]=true; for(i=0;i<sigma_size;i++) //做题时开始忘记这、错了下 if(ch[u][i]) return false; return true;}int main(){ int T; int n,i; scanf("%d",&T); bool flag; while(T--) { flag=true; val[0]=0; memset(ch[0],0,sizeof(ch[0])); cnt=1; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%s",str); if(!insert(str)) flag=false; } if(flag) printf("YES\n"); else printf("NO\n"); } return 0;}
Flying to the Mars
/*题目大意:给你一堆士兵的等级,等级高的的士兵可以当等级小的士兵的师傅,一个士兵最多一个师傅(可以没有),一个师傅最多1个徒弟(可以没有),如果是师徒关系,可以用一把扫帚练习技能,问你如果全部士兵都用过扫帚练习时最小需要的扫帚数量。解题思路:实质就是字典树的应用。如果所有士兵等级都不同,则就可以用一条师徒链,所以就需要一把扫帚,而如果出现2个相同等级的士兵,则需要开辟另外一条师徒链,以此类推,发现只要求出等级相同的最多士兵数,就需要多少把扫帚。*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct Trie{ int cnt; Trie *child[10]; Trie(){cnt=0;memset(child,NULL,sizeof(child));}}*root;int ans;void insert(char *s){ int id; Trie *p=root; for(int i=0;s[i];) { id=s[i]-'0'; if(!p->child[id]) p->child[id]=new Trie(); p=p->child[id]; ++i; } p->cnt++; ans=max(ans,p->cnt);}int main(){ char s[35]; int n,pos; for(;~scanf("%d",&n);) { ans=0; root=new Trie(); for(int i=0;i<n;++i) { scanf("%s",s); pos=0; for(;s[pos]=='0';++pos); insert(s+pos); } printf("%d\n",ans); } return 0;}
魔咒词典
#include<cstdio>#include<algorithm>using namespace std;char str[130];//数据读入所用 char moz[101000][30];//魔咒 char func[101000][90];//对应功能 char Result[130];//结果 int val[101000];//对魔咒排序所用int vafun[101000];//对功能排序所用 int tot=0;//魔咒总个数 bool cmp(int a,int b){//快排魔咒(从小到大,可也以从大到小,看自己喜欢)if(strcmp(moz[a],moz[b])==-1) return true;return false;}//可以直接写成return strcmp(moz[a],moz[b])==-1;bool _cmp(int a,int b){//对功能排序 if(strcmp(func[a],func[b])==-1) return true;return false;}//return strcmp(func[a],func[b])==-1;bool Finda(char *s){//二分查找魔咒 int left=0,right=tot-1,mid;while(left<=right){mid=(left+right)>>1;//mid=(left+right)/2; if(!strcmp(moz[val[mid]],s)){strcpy(Result,func[val[mid]]);//把功能复制给结果Result return true;//返回 }else if(strcmp(moz[val[mid]],s)==1){right=mid-1;}else left=mid+1;}return false;}bool Findb(char *s){//十分查找功能 int left=0,right=tot-1,mid;while(left<=right){mid=(left+right)>>1;if(!strcmp(func[vafun[mid]],s)){strcpy(Result,moz[vafun[mid]]+1);int len=strlen(moz[vafun[mid]]);Result[len-2]='\0';return true;}else if(strcmp(func[vafun[mid]],s)==1){right=mid-1;}else left=mid+1;}return false;}int main(){int i,Q,len;bool flag;while(gets(str),str[0]!='@'){len=strlen(str);for(i=0;str[i];i++){//存入魔咒 moz[tot][i]=str[i];if(str[i]==']') break;}moz[tot][++i]='\0';val[tot]=tot;strcpy(func[tot],str+i+1);//存入功能 func[tot][len-i-1]='\0';vafun[tot]=tot++;}sort(val,val+tot,cmp);sort(vafun,vafun+tot,_cmp);scanf("%d",&Q);getchar();while(Q--){gets(str);if(str[0]=='['){flag=Finda(str);if(flag==false) puts("what?");else puts(Result);}else{flag=Findb(str);if(flag==false) puts("what?");else puts(Result);}memset(Result,0,sizeof(Result));}return 0;}
确定比赛名次
/*简单拓扑排序问题,问题在于选取入度为零的点。*/#include <stdio.h>#define MAX 505#include <string.h> int map[MAX][MAX], N, M, hash[MAX]; void update( int x ){ for( int i= 1; i<= N; ++i ) { map[x][i]= 0; } } void Tsort( ){ for( int i= 1; i<= N; ++i ) { for( int j= 1; j<= N; ++j ) { if( hash[j] ) { continue; } int sign= 1; for( int k= 1; k<= N&& sign; ++k ) { if( map[k][j] ) { sign= 0; break; } } if( sign ) { printf( i== 1? "%d": " %d", j ); hash[j]= 1; update( j ); break; } } } puts( "" );} int main( ){ while( scanf( "%d%d", &N, &M )!= EOF ) { memset( map, 0, sizeof( map ) ); memset( hash, 0, sizeof( hash ) ); for( int i= 1; i<= M; ++i ) { int x, y; scanf( "%d%d", &x, &y ); map[x][y]= 1; } Tsort( ); } return 0;}
产生冠军
#include <stdio.h>#include <string.h>#define MAXN 1005int n, top_name, indegree[MAXN];char name[MAXN][15];void Init(){ top_name = 0; memset(indegree, 0, sizeof(indegree));}int find_str(char *s){ int i; for(i=0; i<top_name; i++){ if(strcmp(name[i], s) == 0) break; } if(i==top_name){ strcpy(name[top_name++], s); } return i;}int main(){ int i, k, cnt, pos1, pos2; char s1[15], s2[15]; while(scanf("%d", &n) == 1 && n){ Init(); for(i=0; i<n; i++){ scanf("%s %s", s1, s2); pos1 = find_str(s1), pos2 = find_str(s2); indegree[pos2]++; } cnt = 0; for(i=0; i<top_name; i++){ if(indegree[i] == 0){k = i; cnt++;} if(cnt > 1) break; } if(cnt == 1) printf("Yes\n"); else printf("No\n"); } return 0;}
Box Relations
/*把一个箱子分成三个面,即X,Y,Z拿X来说,把这个面分为上下两部分,上面记为1,下面记为1+n,当读入X A B条件的时候,那么A箱的下表面和B箱的上表面构成关系,虽然题目中说是A要比B小,但是由于我们最后记录的时候i是从小到大来的,所以我们把A放在B的上面,结果是A的坐标比B小 当读入I A B的时候,那么A箱的上表面大于B箱的下表面,B箱的上表面要大于A箱的下表面,在纸上画个图就很好理解了,接下来就是分成X,Y,Z三个面分别拓扑就好*/ #include <cstdio> #include <cstring> using namespace std; const int N=2010; bool g[3][N][N]; int ind[3][N],n; int topo[3][N]; int x[N],y[N],z[N]; bool toposort(int k) { memset(ind[k],0,sizeof(ind[k])); for(int v=1;v<=n;v++) for(int u=1;u<=n;u++) if(g[k][u][v]) ind[k][v]++; for(int i=0;i<n;i++) { int u; for(u=1;u<=n;u++) if(ind[k][u]==0) break; if(u>n) return false; topo[k][i]=u; ind[k][u]--; for(int v=1;v<=n;v++) if(g[k][u][v]) ind[k][v]--; } return true; } int main() { int m,C=0; while(scanf("%d%d",&n,&m),n||m) { memset(g,0,sizeof(g)); for(int i=0;i<3;i++) for(int u=1;u<=n;u++) g[i][u][u+n]=1; while(m--) { char op[2]; int u,v; scanf("%s%d%d",op,&u,&v); if(op[0]=='I') { for(int i=0;i<3;i++) g[i][v][u+n]=g[i][u][v+n]=1; } else { int k=op[0]-'X'; g[k][u+n][v]=1; } } n*=2; bool flag=true; for(int i=0;flag&&i<3;i++) if(!toposort(i)) flag=false; n/=2; if(flag) { printf("Case %d: POSSIBLE\n",++C); for(int i=0;i<2*n;i++) x[topo[0][i]]=y[topo[1][i]]=z[topo[2][i]]=i; for(int i=1;i<=n;i++) printf("%d %d %d %d %d %d\n",x[i],y[i],z[i],x[i+n],y[i+n],z[i+n]); } else printf("Case %d: IMPOSSIBLE\n",++C); printf("\n"); } return 0; }
Entropy
#include <iostream>#include <cstdlib>#include <cstdio>#include <queue>using namespace std;const int MAXN = 1010;struct node{ int data; int dep; node *L, *R; node() { data = 0; dep = 0; L = NULL; R = NULL; } bool operator <(node a) const { return a.data < data; } //重载小于号 };int ans;char str[MAXN];int huf[MAXN];priority_queue<node> Q;void BuildHuffman(){ node *p, *q, *T; while(Q.size() != 1) { p = new node(); q = new node(); T = new node(); *p = Q.top(); Q.pop(); *q = Q.top(); Q.pop(); T->data = p->data + q->data; T->L = p, T->R = q; Q.push(*T); } return ;}queue<node> q;void solve(){ node root; root = Q.top(); Q.pop(); root.dep = 0; q.push(root); while(!q.empty()) { node x = q.front(); q.pop(); if(x.L) { x.L->dep = x.dep + 1; q.push(*(x.L)); } if(x.R) { x.R->dep = x.dep + 1; q.push(*(x.R)); } if(!x.L && !x.R) { ans += x.dep * x.data; } }}/*void dfs(node *p, int dep){ if(!p->L && !p->R) { ans += p->data * dep; } if(p->L) { dfs(p->L, dep+1); } if(p->R) { dfs(p->R, dep+1); }}*/void init(){ ans = 0; while(!Q.empty()) Q.pop(); while(!q.empty()) q.pop(); memset(huf, 0, sizeof(huf));}int main(){ while(scanf("%s", str) && strcmp(str, "END")) { init(); int len = strlen(str); for(int i = 0; str[i]; i++) { huf[str[i]]++; } for(int i = 0; i < 100; i++) if(huf[i]) { node t; t.data = huf[i]; Q.push(t); } if(Q.size() == 1) //特判 { printf("%d %d 8.0\n", len*8, len); continue; } BuildHuffman(); solve(); //dfs(root, 0); 用DFS也可以实现 printf("%d %d %.1lf\n", len*8, ans, len*8.0/ans); } return 0;}