bzoj 1055: [HAOI2008]玩具取名
Posted qt666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1055: [HAOI2008]玩具取名相关的知识,希望对你有一定的参考价值。
Description
某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后
他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
Input
第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。接下来W行,每行两个字母,表示W可
以用这两个字母替代。接下来I行,每行两个字母,表示I可以用这两个字母替代。接下来N行,每行两个字母,表示N
可以用这两个字母替代。接下来G行,每行两个字母,表示G可以用这两个字母替代。最后一行一个长度不超过Len的
字符串。表示这个玩具的名字。
Output
一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)如果给的名字不能由任何一个字母
变形而得到则输出“The name is wrong!”
Sample Input
1 1 1 1
II
WW
WW
IG
IIII
II
WW
WW
IG
IIII
Sample Output
IN
HINT
W可以变成II所以IIII可以缩成WW IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序
输出IN
[数据范围]
100%数据满足Len<=200,W、I、N、G<=16
Source
算是最基础的区间dp类型了,设dp[i][j][k],表示[i,j]能否由k变来;
题目里面说明了每个字母都可以由两个字母变来,那么我们容易想到把[i,j]枚举断点分为两个区间,然后合并两个区间的信息,就是n^3的那种区间dp;
实现的话,区间dp最好都是写记忆化搜索,这样就不会有转移顺序的问题;
//MADE BY QT666 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; typedef long long ll; const int N=300; bool dp[N][N][5],bj[N][N][5]; struct data{ int x,y; }; vector<data> g[N]; char ch[N]; int s[N]; bool dfs(int l,int r,int p){ if(l==r){ bj[l][r][p]=1; dp[l][r][p]=(s[l]==p); return dp[l][r][p]; } if(bj[l][r][p]) return dp[l][r][p]; for(int k=l;k<r;k++){ for(int i=0;i<g[p].size();i++){ dp[l][r][p]|=(dfs(l,k,g[p][i].x)&&dfs(k+1,r,g[p][i].y)); if(dp[l][r][p]) break; } if(dp[l][r][p]) break; } bj[l][r][p]=1;return dp[l][r][p]; } void read(int xh,int sz){ for(int i=1;i<=sz;i++){ scanf("%s",ch+1);int x,y; if(ch[1]==‘W‘) x=1; if(ch[1]==‘I‘) x=2; if(ch[1]==‘N‘) x=3; if(ch[1]==‘G‘) x=4; if(ch[2]==‘W‘) y=1; if(ch[2]==‘I‘) y=2; if(ch[2]==‘N‘) y=3; if(ch[2]==‘G‘) y=4; g[xh].push_back((data){x,y}); } } int main(){ int w,i,n,g; scanf("%d%d%d%d",&w,&i,&n,&g); read(1,w);read(2,i);read(3,n);read(4,g); scanf("%s",ch+1);int len=strlen(ch+1); for(int i=1;i<=len;i++){ if(ch[i]==‘W‘) s[i]=1; if(ch[i]==‘I‘) s[i]=2; if(ch[i]==‘N‘) s[i]=3; if(ch[i]==‘G‘) s[i]=4; } int flg=0; for(int i=1;i<=4;i++){ if(dfs(1,len,i)){ if(i==1) cout<<"W"; if(i==2) cout<<"I"; if(i==3) cout<<"N"; if(i==4) cout<<"G"; flg=1; } } if(!flg) puts("The name is wrong!"); return 0; }
以上是关于bzoj 1055: [HAOI2008]玩具取名的主要内容,如果未能解决你的问题,请参考以下文章