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;
}
5.2.4 HDU1285 确定比赛名次
输入数据保证有序,那就是赤果果的拓扑排序了
输入有点阴,会有重复边,注意不要把入度算多了!
#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;
}
5.2.5 HDU2094 产生冠军
首先转换字符串为标号,然后建图
冠军存在的条件是,有且仅有一个入度为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;
}
5.2.8 HDU2527 Safe Or Unsafe
也是Huffman编码 代码和上面差不多