区间DP/记忆化搜索
sigh……看了提示才想到是区间DP >_>我果然还是太弱
f[l][r][k]表示L到R这段区间能否合并成K,那么就是枚举拆分方案(从哪里断开)和组合方式(左半合成的子母+右半合成的子母 可以合成 K)了……
记忆化搜索即可= =
1 /************************************************************** 2 Problem: 1055 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:1040 ms 7 Memory:2136 kb 8 ****************************************************************/ 9 10 //BZOJ 1055 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 inline int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=210,INF=~0u>>2; 29 typedef long long LL; 30 /******************tamplate*********************/ 31 inline int id(char ch){ 32 if (ch=='W') return 1; 33 if (ch=='I') return 2; 34 if (ch=='N') return 3; 35 if (ch=='G') return 4; 36 } 37 char s[N]; 38 int f[N][N][5],a[N],n,num[5]; 39 vector<int>G[5]; 40 bool dfs(int l,int r,int k){ 41 if (f[l][r][k]!=-1) return f[l][r][k]; 42 if (l==r) return f[l][r][k]=a[l]==k; 43 rep(i,G[k].size()){ 44 int t1=G[k][i]/10,t2=G[k][i]%10; 45 F(j,l,r-1) 46 if (dfs(l,j,t1) && dfs(j+1,r,t2)) return f[l][r][k]=1; 47 } 48 return f[l][r][k]=0; 49 } 50 int main(){ 51 #ifndef ONLINE_JUDGE 52 freopen("1055.in","r",stdin); 53 freopen("1055.out","w",stdout); 54 #endif 55 memset(f,-1,sizeof f); 56 F(i,1,4) num[i]=getint(); 57 F(i,1,4) F(j,1,num[i]){ 58 char s[4]; 59 scanf("%s",s); 60 int x=id(s[0])*10+id(s[1]); 61 G[i].pb(x); 62 } 63 scanf("%s",s); 64 n=strlen(s); 65 F(i,1,n) a[i]=id(s[i-1]); 66 bool sign=0; 67 if (dfs(1,n,1)) {printf("W"); sign=1;} 68 if (dfs(1,n,2)) {printf("I"); sign=1;} 69 if (dfs(1,n,3)) {printf("N"); sign=1;} 70 if (dfs(1,n,4)) {printf("G"); sign=1;} 71 if (!sign) printf("The name is wrong!"); 72 return 0; 73 }
1055: [HAOI2008]玩具取名
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 960 Solved: 566
[Submit][Status][Discuss]
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