爱悠闲 > BZOJ 1055 HAOI2008 玩具取名 动态规划

BZOJ 1055 HAOI2008 玩具取名 动态规划

分类: BZOJ  |  标签: BZOJ,BZOJ1055,动态规划  |  作者: popoqqq 相关  |  发布日期 : 2014-10-06  |  热度 : 860°

题目大意:给定一个由‘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!");
}