bzoj 1055: [HAOI2008]玩具取名(区间DP)

本文介绍了一种使用区间动态规划方法解决特定字符串缩合问题的算法实现。该问题要求将连续的一段字符串缩合成单个字符,并且长字符串能否缩合取决于短字符串缩合后的结果。通过枚举中间点和操作进行状态转移,最终实现了解决方案。

传送门

戳戳戳


题解

貌似我就没写过几道区间DP的题,好像除了石子合并和某四边形优化果题就没了。。

这题要求让连续的一段缩起来,而且长的能不能缩取决于短的缩出来的是什么。于是这就是一个区间DP了。

设dp[x][l][r]表示从l到r缩成x是否可行。我们枚举中间点k和操作就可以转移了。区间DP的k的取值一般是左闭右开的,我又回忆起来了。嗯。


代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#define maxn 222

using namespace std;

char s[5], S[maxn];

int a[maxn], b[maxn], c[maxn];
int n1, n2, n3, n4, n, len;
bool dp[maxn][maxn][maxn];

int main(){

    scanf("%d%d%d%d", &n1, &n2, &n3, &n4);

    n = n1 + n2 + n3 + n4;

    for(int i = 1; i <= n; i++){
        scanf("%s", s);
        a[i] = s[0]-'A';
        b[i] = s[1]-'A';
        if(i <= n1)  c[i] = 'W'-'A';
        else if(i <= n1+n2)  c[i] = 'I'-'A';
        else if(i <= n1+n2+n3)  c[i] = 'N'-'A';
        else  c[i] = 'G'-'A';
    }

    scanf("%s", S);
    len = strlen(S);

    for(int i = 1; i <= len; i++)
        dp[S[i-1]-'A'][i][i] = true;

    for(int l = 2; l <= len; l++)
        for(int i = 1; i <= len-l+1; i++){
            int j = i + l - 1;
            for(int k = i; k < j; k++)
                for(int p = 1; p <= n; p++)
                    dp[c[p]][i][j] |= dp[a[p]][i][k] && dp[b[p]][k+1][j];
        }

    bool WY = false;

    if(dp['W'-'A'][1][len])  putchar('W'), WY = true;
    if(dp['I'-'A'][1][len])  putchar('I'), WY = true;
    if(dp['N'-'A'][1][len])  putchar('N'), WY = true;
    if(dp['G'-'A'][1][len])  putchar('G'), WY = true;

    if(!WY)  puts("The name is wrong!");

    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值