LGP4290

难度在省选左右.

主要思路是dp,在看了题解后才明白,主要谈谈理解.

看上去与dp毫无关系,但这个题不是利用dp求最优值,而是利用dp的子结构的递推关系.

对于长为len的字符串,可以分成很多个1个单独字符与两个字符的组合(这两个字符可变成

一字符),大串能否转换,看其构成的小串能转换.所以以长度为1开始递推到len.

f[i][j][k]:从串的i到j能否装换为字符k; ps:f[i][i][s[i]]=1(自己能转换自己.)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define R register
const int maxn=310;
char s[maxn];
int tot[maxn],f[maxn][maxn][5],q[maxn][5],cnt,len;
int check(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(R int i=1;i<=4;++i)
        scanf("%d",&tot[i]);
    for(R int i=1;i<=4;++i)
    {
        for(R int j=1;j<=tot[i];++j)
        {
            char k[10];
            scanf("%s",k);//不加&
            q[++cnt][0]=i;
            q[cnt][1]=check(k[0]);
            q[cnt][2]=check(k[1]);
        }
    }
    scanf("%s",s+1);
    len=strlen(s+1);//注意strlen(s+1)!=strlen(s)+1;
    for(R int i=1;i<=len;++i)
        f[i][i][check(s[i])]=1;
    for(R int i=len;i>=1;--i)
        for(R int j=i+1;j<=len;++j)
            for(R int k=i;k<j;++k)//k+1<j =>k<j;
                for(R int t=1;t<=cnt;++t)
                    if(f[i][k][q[t][1]]&&f[k+1][j][q[t][2]])
                        f[i][j][q[t][0]]=1;
    int flag=0;
    if(f[1][len][1]) 
        flag=1,cout<<"W";
    if(f[1][len][2])
        flag=2,cout<<"I";
    if(f[1][len][3])
        flag=3,cout<<"N";
    if(f[1][len][4])
        flag=4,cout<<"G";
    if(!flag)
        cout<<"The name is wrong!";
    return 0;
}
原文地址:https://www.cnblogs.com/xqysckt/p/11194934.html