5.2.1 HDU1075 What Are You Talking About
简单的字典树,在翻译时注意一点小问题,字符串的问题就是处理有些麻烦..
#include <cstdio> #include <string.h> #include <cstdlib> using namespace std; char line[30],s1[12],s2[12],tline[3010]; struct trie{ trie *next[26];char c[12];int has; trie(){for(int i=0;i<26;i++)next[i]=NULL;has=0;} }*root; void instrie(char s11[12],char s12[12]){ int len=strlen(s12); trie *p=root; for(int i=0;i<len;i++){ int t=s12[i]-'a'; if(p->next[t]==NULL)p->next[t]=new trie; p=p->next[t]; } p->has=1; strcpy(p->c,s11); } bool search(char s11[12]){ int len=strlen(s11); trie *p=root; for(int i=0;i<len;i++){ int t=s11[i]-'a'; if(p->next[t]==NULL)return false; p=p->next[t]; } if(p->has==0)return false; strcpy(s2,p->c); return true; } int main(){ root=new trie; while(gets(line)){ if(strcmp(line,"START")==0)continue; if(strcmp(line,"END")==0)break; sscanf(line,"%s%s",s1,s2); instrie(s1,s2); } while(gets(tline)){ if(strcmp(tline,"START")==0)continue; if(strcmp(tline,"END")==0)break; int i=0,j=0,len=strlen(tline); while(i<len){ if(tline[i]<'a'||tline[i]>'z'){ //查找这个单词,找到输出对应的单词,找不到直接输出原文 s1[j]='\0'; if(search(s1))printf("%s",s2); else printf("%s",s1); //打印标点,开始搜索下一个单词 printf("%c",tline[i]); j=0,i++; }else{ s1[j]=tline[i]; i++,j++; } } printf("\n"); } }
5.2.2 HDU1251 统计难题
字典树,经过的字母标记全部加一,查找的时候返回该字母的标记
5.2.3 HDU1671 Phone List
判断一组字符串,有没有字符串是其它字符串的前缀
读入的时候就可以判断该字符串是不是其它字符串的前缀,或者后缀..用一个标记标记该位置是否为单词结尾
如果存入单词的结尾处已经有单词经过,说明存入单词是另一单词的前缀,如果存入单词经过的地方有其它单词的结尾,说明另一单词是存入单词的前缀..这两种情况都返回false
int instrie(char s1[11]){ int len=strlen(s1); int r=1; trie *p=root; for(int i=0;i<len;i++){ int t=s1[i]-'0'; //是其它单词的前缀 if(i==len-1&&p->next[t]!=NULL)r=0; if(p->next[t]==NULL)p->next[t]=new trie; p=p->next[t]; //其它单词是它的前缀 if(p->e==1)r=0; } p->e=1;//标记在这里结束 return r; }
输入数据保证有序,那就是赤果果的拓扑排序了
输入有点阴,会有重复边,注意不要把入度算多了!
#include <cstdio> #include <string.h> using namespace std; const int MAXN=505; int map[MAXN][MAXN],n,m,a,b,in[MAXN],ans[MAXN]; void topo(){ int top=1,u; memset(ans,0,sizeof ans); while(1){ for(u=1;u<=n;u++)if(in[u]==0)break; if(u==n+1)return; in[u]=-1; ans[top++]=u; for(int v=1;v<=n;v++)if(map[u][v]==1)in[v]--; } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ memset(map,0,sizeof map); memset(in,0,sizeof in); while(m--){ scanf("%d%d",&a,&b); if(map[a][b]==0)map[a][b]=1,in[b]++; } topo(); printf("%d",ans[1]); for(int i=2;i<=n;i++)printf(" %d",ans[i]); printf("\n"); } return 0; }
首先转换字符串为标号,然后建图
冠军存在的条件是,有且仅有一个入度为0的点并且这个从这个点可以访问到其它所有点
5.2.6 HDU3231 Box Relations
一道好题,但是不会做...建图比较难,三个轴都要建图,然后分别拓扑排序,排序失败的话就说明impossible了..
代码不是我自己写的,基本都是模仿大牛的代码的..
#include <cstdio> #include <string.h> using namespace std; int n,r,a,b,ne; char c; struct node{int v,next;node(){};node(int a,int b){next=a,v=b;}}e[500000]; int head[4][2001],ind[4][2001],ans[4][2001],q[4][2001]; //邻接表建图 void ins(int op,int u,int v){ e[ne]=node(head[op][u],v); head[op][u]=ne++; ind[op][v]++; } //初始化,注意初始化每个立方体本身边的关系 void init(){ ne=0; memset(ind,0,sizeof ind); memset(head,-1,sizeof head); for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)ins(j,i,i+n); } //拓扑排序,返回是否成功 bool topo(int op){ int front=0,top=0; for(int i=1;i<=2*n;i++) if(ind[op][i]==0)q[op][top++]=i,ind[op][i]--; while(front<top){ int u=q[op][front++]; for(int i=head[op][u];i!=-1;i=e[i].next){ int v=e[i].v; ind[op][v]--; if(ind[op][v]==0)q[op][top++]=v,ind[op][v]--; } } return top==2*n; } void solve(){ for(int i=1;i<=3;i++){ if(!topo(i)){printf("IMPOSSIBLE\n");return;} } printf("POSSIBLE\n"); //根据拓扑关系决定答案 for(int k=1;k<=3;k++)for(int i=0;i<2*n;i++)ans[k][q[k][i]]=i; for(int i=1;i<=n;i++){ printf("%d %d %d ",ans[1][i],ans[2][i],ans[3][i]); printf("%d %d %d\n",ans[1][i+n],ans[2][i+n],ans[3][i+n]); } } int main(){ int cas=1; while(scanf("%d%d",&n,&r),n||r){ init(); while(r--){ scanf(" %c%d%d",&c,&a,&b); if(c=='I'){ for(int i=1;i<=3;i++){ ins(i,a,b+n); ins(i,b,a+n); } }else{ ins(c-'X'+1,a+n,b); } } printf("Case %d: ",cas++); solve(); printf("\n"); } }
5.2.7 HDU1053 Entropy
描述一大敌,其实就是Huffman编码,用优先队列实现,注意只有一种字符的情况
#include <cstdio> #include <queue> #include <string.h> using namespace std; char line[10000]; int pl[27],len; int main(){ while(scanf("%s",line)){ if(strcmp(line,"END")==0)break; //统计频度 memset(pl,0,sizeof pl); len=strlen(line); for(int i=0;i<len;i++){ if(line[i]=='_')pl[0]++; else pl[line[i]-'A'+1]++; } //判断是否单一字符 int yes=0; for(int i=0;i<27;i++){ if(pl[i]==len){ printf("%d %d 8.0\n",len*8,len); yes=1; break; } } if(yes)continue; //使用优先队列统计HUFFMAN编码 priority_queue<int,vector<int>,greater<int> > q; int ans=0,a,b; for(int i=0;i<27;i++)if(pl[i]!=0)q.push(pl[i]); while(1){ int a=q.top();q.pop(); if(q.empty())break; int b=q.top();q.pop(); ans+=a+b; q.push(a+b); } printf("%d %d %.1lf\n",len*8,ans,len*8.0/ans); } return 0; }
也是Huffman编码 代码和上面差不多