洛谷题单指南-动态规划3-P4290 [HAOI2008] 玩具取名

原题链接:https://www.luogu.com.cn/problem/P4290

题意解读:W、I、N、G中一个字母可以替换为多种两个字母,给定目标串,求能从W、I、N、G中哪些单个字母变形得到。

解题思路:

1、状态表示:

设W、I、N、G为1、2、3、4,函数int getnum(char c)用于将字符转换为对应整数,

设ok[i][j][k]=1表示ij可以由k变形而来,ijk是1、2、3、4,代表W、I、N、G,

设dp[i][j][z]表示i~j的字符串能否从k(取值1-4)变形而来,值为1或0,

设目标字符串为s。

2、状态转移

枚举i~j之间的分界点k,再枚举xyz(取值1-4),如果dp[i][k][x] && dp[k+1][j][y] && ok[x][y][z],说明dp[i][j][z] = 1

3、初始化:

根据输入数据填充ok[][][]

dp[i][i][getnum(s[i])] = 1,表示一个字符可以从自身变形过来。

4、结果

如果dp[1][n][1] = 1,输出'W'

如果dp[1][n][2] = 1,输出'I'

如果dp[1][n][3] = 1,输出'N'

如果dp[1][n][4] = 1,输出'G'

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 205;
int cnt[5];
string s;
bool ok[5][5][5];
bool dp[N][N][5];

int getnum(char c)
{
    if(c == 'W') return 1;
    if(c == 'I') return 2;
    if(c == 'N') return 3;
    if(c == 'G') return 4;
}

int main()
{
    cin >> cnt[1] >> cnt[2] >> cnt[3] >> cnt[4];
    char l, r;
    for(int i = 1; i <= 4; i++)
    {
        for(int j = 1; j <= cnt[i]; j++)
        {
            cin >> l >> r;
            ok[getnum(l)][getnum(r)][i] = 1;
        }
        
    }
    cin >> s;
    int n = s.size();
    s = " " + s; //字符串从1开始
    for(int len = 1; len <= n; len++) //枚举区间长度
    {
        for(int i = 1; i + len - 1 <= n; i++) //枚举左端点
        {
            int j = i + len - 1; //计算右端点
            if(len == 1) 
            {
                dp[i][j][getnum(s[i])] = 1;
            }
            else
            {
                for(int k = i; k < j; k++) //枚举分界点
                {
                    for(int x = 1; x <= 4; x++)
                    {
                        for(int y = 1; y <= 4; y++)
                        {
                            for(int z = 1; z <= 4; z++)
                            {
                                if(dp[i][k][x] && dp[k+1][j][y] && ok[x][y][z])
                                {
                                    dp[i][j][z] = 1;
                                }  
                            }
                        }
                    }
                }
            }
        }
    }

    bool yes = false;
    if(dp[1][n][1]) yes = true, cout << "W";
    if(dp[1][n][2]) yes = true, cout << "I";
    if(dp[1][n][3]) yes = true, cout << "N";
    if(dp[1][n][4]) yes = true, cout << "G";
    if(!yes) cout << "The name is wrong!";

    return 0;
}

 

posted @ 2024-05-14 11:10  五月江城  阅读(13)  评论(0编辑  收藏  举报