BZOJ 1055 HAOI2008 玩具取名 动态规划

题目大意:给定一个由‘W','I','N','G'构成的字符串。给定一些规则。这些规则能够将两个字符合成为一个,比如"II"能够合成为'W',"WW"能够合成为'I'或者'N'

求这个字符串能够终于合成为哪几种字符

看到这题我想到了广搜。

。。事实上不是必需,动归全然能够解决

令f[i][j][k]为从i開始的j个字符能否够合成为字符[k]

然后j从外层循环。剩下的所有预处理,怎么暴力怎么转移。我写了六层循环,有点吓人

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 210
using namespace std;
int n,W,I,N,G;
int trans[4][4][4];
bool f[M][M][4],flag;
char s[M],table[5]="WING";
inline int GetInt(char c)
{
switch(c)
{
case 'W':return 0;
case 'I':return 1;
case 'N':return 2;
case 'G':return 3;
}
}
inline void Input(int p)
{
int x,y;
char c[2];
scanf("%s",c);
x=GetInt(c[0]);
y=GetInt(c[1]);
trans[x][y][p]=1;
}
int main()
{
int i,j,k,c1,c2,c3;
cin>>W>>I>>N>>G;
for(i=1;i<=W;i++)
Input(0);
for(i=1;i<=I;i++)
Input(1);
for(i=1;i<=N;i++)
Input(2);
for(i=1;i<=G;i++)
Input(3);
scanf("%s",s+1);
n=strlen(s+1);
for(i=1;i<=n;i++)
f[i][1][ GetInt(s[i]) ]=1;
for(j=2;j<=n;j++)
for(i=1;i+j-1<=n;i++)
for(k=i;k<i+j-1;k++)
for(c1=0;c1<4;c1++)
if(f[i][k-i+1][c1])
for(c2=0;c2<4;c2++)
if(f[k+1][i+j-1-k][c2])
for(c3=0;c3<4;c3++)
if(trans[c1][c2][c3])
f[i][j][c3]=1;
for(i=0;i<4;i++)
if(f[1][n][i])
flag=1,putchar(table[i]);
if(!flag)
puts("The name is wrong!");
}
上一篇:BZOJ1055[HAOI2008]玩具取名 【区间dp + 记忆化搜索】


下一篇:【记忆化搜索】bzoj1055 [HAOI2008]玩具取名