bzoj1055 ||P4290 [HAOI2008]玩具取名

本文介绍了一种使用区间动态规划解决字符转换问题的方法。通过枚举长度、起点和中点,实现暴力转移,适用于字符种类不多的情况。文章提供了一个C++代码示例,详细展示了如何实现区间DP算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接

luogu
bzoj

思路

区间dp
然后\(f[i][j][k]\) 区间\([i,j]\)能否变成\(k\)字符 (字符当然得转化一下)
字符的个数不多,直接暴力\(check\),暴力转移就行,\(%%gzy\)
区间dp还是挺套路模板
只不过看着恶心,其实真不恶心

for枚举长度
      for枚举起点
            计算终点
            for枚举中点
                   大力转移

代码

/**************************************************************
    Problem: 1055
    User: 3010651817
    Language: C++
    Result: Accepted
    Time:404 ms
    Memory:1500 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define NO puts("The name is wrong!")
using namespace std;
const int maxn=207;
char Q[5]= {'\0','W','I','N','G'},s[maxn];
bool z[5][5][5];
int n,zhong[5],cnt;
bool f[maxn][maxn][5];
map<string,int> a;
int calc(char zz) {
    if(zz=='W') return 1;
    if(zz=='I') return 2;
    if(zz=='N') return 3;
    return 4;
}
int main() {
    for(int i=1; i<=4; ++i) scanf("%d",&zhong[i]);
    for(int i=1; i<=4; ++i) {
        char a[3];
        for(int j=1; j<=zhong[i]; ++j) {
            scanf("%s",a);
            z[i][calc(a[0])][calc(a[1])]=1;
        }
    }
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=1; i<=n; ++i) {
        f[i][i][calc(s[i])]=1;
    }
    for(int len=1; len<n; ++len) {
        //长度
        for(int i=1; i<=n; ++i) {
            //起点
            int j=i+len;
            if(j>n) break; //终点
            for(int k=i; k<j; ++k) {
                //中点
                for(int i_=1; i_<=4; ++i_) {
                    if(f[i][k][i_])
                    //枚举并且chenk(i,k)
                        for(int j_=1; j_<=4; ++j_) {
                            if(f[k+1][j][j_]) {
                                //枚举并且check(k+1,j)
                                for(int k_=1; k_<=4; ++k_) {
                                    if(z[k_][i_][j_]==1) {
                                        //合并
                                        f[i][j][k_]=1;
                                    }
                                }
                            }
                        }
                }
            }
        }
    }
    for(int i=1; i<=4; ++i) {
        if(f[1][n][i]) {
            cnt++;
            printf("%c",Q[i]);
        }
    }
    if(!cnt) NO;
    return 0;
}

转载于:https://www.cnblogs.com/dsrdsr/p/9789746.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值