sgu 273Game Po (区间dp)

来源:互联网 发布:淘宝中老年装 编辑:程序博客网 时间:2024/06/03 05:54

题意:

4种颜色,两个混合可以组成另一种,给出所有组合以及组合后的结果,给一串颜色,任意位置合并最后合并成一个颜色的所有可能性

tip:

dp[I][j][k]表示从I到j是否可以变成第k个颜色,注意可能有同样两种颜色组合,但形成不一样的颜色,所以我用了前向星把他们连起来,而且从I到j形成的颜色也可能是多个,也用了前向星,循环中间位置m 枚举I到m和m+1到j可能形成的颜色 在循环这两个颜色组成的颜色,就可以更新dp[I][j][k]了,最后枚举dp[1][n][0/1/2/3]谁可能,保存下来即可

#include <cstdio>#include <iostream>#include <cstring>using namespace std;const int maxn = 201;bool dp[maxn][maxn][4];int to[4][4],num[4],mp[26],len,n;char mpb[4],s[210];struct node{    int v,next;}E[4*4*4],edges[maxn*maxn*4];int first[4][4],tot,tt,head[maxn][maxn];void add(int u,int m,int v){    E[tt].v = v;E[tt].next = first[u][m];first[u][m] = tt++;}void addr(int i,int j,int v){    edges[tot].v = v;edges[tot].next = head[i][j];head[i][j] = tot++;}void init(){    tt = tot = 0;    memset(head,-1,sizeof(head));    memset(first,-1,sizeof(first));    for(int i = 0 ; i < 4; i++){        scanf("%d",&num[i]);    }    for(int i = 0 ; i < 4; i++){        for(int j = 0 ; j < num[i]; j++){            scanf("%s",s);            add(mp[s[0]-'a'],mp[s[1]-'a'] , i);        }    }    scanf("%s",s+1);    n = strlen(s+1);    for(int i = 1 ; i <= n ; i++){        dp[i][i][mp[s[i]-'a']] = true;        addr(i,i,mp[s[i]-'a']);    }}void sov(){    for(int len = 2; len <= n ; len++){        for(int i = 1 ; i + len-1 <= n; i++){            int j = len+i-1;            for(int m = i ; m < j ; m++){                for(int k = head[i][m] ; k != -1; k = edges[k].next){                    int v = edges[k].v;                    for(int p = head[m+1][j] ; p != -1 ; p = edges[p].next){                        int e = edges[p].v;                        for(int an = first[v][e];an != -1 ;an = E[an].next){                            if(!dp[i][j][E[an].v])                                addr(i,j,E[an].v);                            dp[i][j][E[an].v] = true;                        }                    }                }            }        }    }}char ans[4];void print(){    int cnt = 0;    for(int i = 0 ; i < 4; i++){        if(dp[1][n][i] ){            ans[cnt++] = mpb[i];        }    }    if(cnt == 0)    printf("Nobody\n");    else{        for(int i = 0 ; i < cnt ;i++)            printf("%c",ans[i]);        printf("\n");    }}int main(){    mp['b'-'a'] = 0;mpb[0] = 'b';    mp['r'-'a'] = 1;mpb[1] = 'r';    mp['y'-'a'] = 2;mpb[2] = 'y';    mp['w'-'a'] = 3;mpb[3] = 'w';    init();    sov();    print();}