bzoj1055玩具取名——区间DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1055

区间DP,注意初始化!!

因为没记忆化,TLE了一晚上,区间DP尤其要注意不重复递归!!!!!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const MAXN=80,LEN=205;
int p[5][5][MAXN],a[LEN],top[5],ln,tp[5][5];
char dc[LEN];
bool can[LEN][LEN][5],flag,f[5],vis[LEN][LEN];
int in(char c)
{
    if(c=='W')return 1;
    if(c=='I')return 2;
    if(c=='N')return 3;
    if(c=='G')return 4;
}
char out(int x)
{
    flag=1;
    if(x==1)return 'W';
    if(x==2)return 'I';
    if(x==3)return 'N';
    if(x==4)return 'G';
}
void cl(int i,char c[])
{
    int k1=in(c[0]),k2=in(c[1]);
    p[k1][k2][++tp[k1][k2]]=i;
}
//void find0(int x,int y)
//{
//    for(int i=1;i<=tp[x][y];i++)
//        f[p[x][y][i]]=1;
//}
//void find(int l,int r,int x,int y)
//{
//    for(int i=1;i<=tp[x][y];i++)
//        can[l][r][p[x][y][i]]=1;
//}
void dp(int l,int r)
{
    if(vis[l][r])return;//大剪枝!!!!! 
    vis[l][r]=1;
    if(r==l)
//    {
//        find(l,r,a[l],a[r]);
        return;
//    }
    for(int k=l;k<r;k++)
    {
        dp(l,k);
        dp(k+1,r);
        for(int x=1;x<=4;x++)
            for(int y=1;y<=4;y++)
                if(can[l][k][x]&&can[k+1][r][y])
                    for(int i=1;i<=tp[x][y];i++)
                        can[l][r][p[x][y][i]]=1;
//                    find(l,r,x,y);
    }
}
int main()
{
    for(int i=1;i<=4;i++)
        scanf("%d",&top[i]);
    for(int i=1;i<=4;i++)
        for(int j=1;j<=top[i];j++)
        {
            cin>>dc;
            cl(i,dc);
        }
    cin>>dc;
    ln=strlen(dc);
    for(int i=1;i<=ln;i++)//初始化 
    {
        can[i][i][in(dc[i-1])]=1;
//        p[dc[i-1]][dc[i-1]][++tp[dc[i-1]][dc[i-1]]]=in(dc[i-1]);
    }
    for(int k=1;k<ln;k++)
    {
        dp(1,k);
        dp(k+1,ln);
        for(int x=1;x<=4;x++)
            for(int y=1;y<=4;y++)
                if(can[1][k][x]&&can[k+1][ln][y])
                    for(int i=1;i<=tp[x][y];i++)
                        f[p[x][y][i]]=1;
//                    find0(x,y);
    }
    for(int i=1;i<=4;i++)
        if(f[i])printf("%c",out(i));
    if(!flag)printf("The name is wrong!");
    return 0;
}

 

posted @ 2018-03-28 00:24  Zinn  阅读(156)  评论(0编辑  收藏  举报