1. 程式人生 > >bzoj1055: [HAOI2008]玩具取名(dp)

bzoj1055: [HAOI2008]玩具取名(dp)

print mem str mic 簡單的 所有 return space name

1055: [HAOI2008]玩具取名

題目:傳送門

簡要題意:

     就是固定四個字母,給出這四個字母分別可以由哪兩個字母組成,然後在給你一個字符串,要求把這個字符串還原成原始的四個字母的其中一個。

題解:

   一開始看題有點瞎...想了想是一道超級大難題...

   其實就是一個很簡單的DP...

   定義發f[i][j][s]:表示在字符串中i~j這個區間是否可以組合成為字符s

   轉移很容易就可以想出來:因為如果f[i][k][s1]==f[k+1][j][s2]==1(i<=k<=j) && s1和s2可以組成s,那麽f[i][j][s]=1;

   O(n^4)...大水題

代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 char s[210];
 8 struct node
 9 {
10     char s1,s2,id;
11 }st[210];
12 bool f[210][210][210];
13 int main()
14 { 15 int W,I,N,G;bool bk=false; 16 scanf("%d%d%d%d",&W,&I,&N,&G); 17 int len=0; 18 for(int i=1;i<=W;i++) 19 scanf("%s",s+1),st[++len].s1=s[1],st[len].s2=s[2],st[len].id=W; 20 for(int i=1;i<=I;i++) 21 scanf("%s",s+1),st[++len].s1=s[1
],st[len].s2=s[2],st[len].id=I; 22 for(int i=1;i<=N;i++) 23 scanf("%s",s+1),st[++len].s1=s[1],st[len].s2=s[2],st[len].id=N; 24 for(int i=1;i<=G;i++) 25 scanf("%s",s+1),st[++len].s1=s[1],st[len].s2=s[2],st[len].id=G; 26 scanf("%s",s+1); 27 int len1=strlen(s+1); 28 memset(f,0,sizeof(f)); 29 for(int i=1;i<=len1;i++)f[i][i][s[i]]=true; 30 for(int i=2;i<=len1;i++)//長度 31 for(int l=1;l<=len1-i+1;l++)//左端點 32 { 33 int r=l+i-1; 34 for(int j=l;j<=r;j++)//斷點 35 for(int k=1;k<=len;k++)//枚舉所有種類的字符串 36 if(f[l][j][st[k].s1] && f[j+1][r][st[k].s2]) 37 f[l][r][st[k].id]=true; 38 } 39 W=W;I=I;N=N;G=G; 40 if(f[1][len1][W])printf("W"),bk=true; 41 if(f[1][len1][I])printf("I"),bk=true; 42 if(f[1][len1][N])printf("N"),bk=true; 43 if(f[1][len1][G])printf("G"),bk=true; 44 if(bk==false)printf("The name is wrong!\n"); 45 return 0; 46 }

bzoj1055: [HAOI2008]玩具取名(dp)