题目大意不说了。
区间\(dp\)
设计\(dp[i][j][k]\)表示区间\([i,j]\)能不能由字符\(k\)变化得到
那么有一个状态转移方程是:
\[dp[i][j][lay[l][0]]=dp[i][mid][lay[l][1]]>0,dp[mid+1][j][lay[l][2]]>0\]
\(lay\)数组是存储的变化信息。\(lay[l][1]\)表示的变化信息第\(l\)条的第一个字符,以此类推。\(lay[l][0]\)是这条信息所指的字符
\(Code:\)
#include<bits/stdc++.h> using namespace std; int num[6]; int cnt; char s[2010]; int lay[2000][5]; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); } return s*w; } int dp[201][202][5]; inline int Number(char c){ if(c=='W')return 1; if(c=='I')return 2; if(c=='N')return 3; if(c=='G')return 4; } int main(){ for(int i=1;i<=4;++i)num[i]=read(); for(int i=1;i<=4;++i) for(int j=1;j<=num[i];++j){ char cc; cin>>cc; lay[++cnt][0]=i; lay[cnt][1]=Number(cc); cin>>cc; lay[cnt][2]=Number(cc); } scanf("%s",s+1);int n=strlen(s+1); for(int i=1;i<=n;++i)dp[i][i][Number(s[i])]=1; for(int i=n;i>=1;--i) for(int j=i;j<=n;++j) for(int k=i;k<=j;++k) for(int l=1;l<=cnt;++l) if(dp[i][k][lay[l][1]]&&dp[k+1][j][lay[l][2]]) dp[i][j][lay[l][0]]=1; int C=0; if(dp[1][n][1])cout<<'W',C++; if(dp[1][n][2])cout<<'I',C++; if(dp[1][n][3])cout<<'N',C++; if(dp[1][n][4])cout<<'G',C++; if(!C)cout<<"The name is wrong!"; cout<<endl; return 0; }
来源:https://www.cnblogs.com/h-lka/p/12219043.html