洛谷 P4290 [HAOI2008]玩具取名

传送门

思路

博客半年没更新了,来更新个博文吧

\(dsr\)聚聚博客的帮助下,我用半个上午和一个中午的时间苟延残喘地完成了这道题

先是读题目读大半天,最后连个样例都看不懂

之后又是想思路,实在想不出来,便去看了\(dsr\)学长的博客,发现是一道区间\(DP\)

我们用\(f[i][j][k]\)来表示\(i\)\(j\)这个区间能否压缩成为\(k\)这个字符

基本框架为

枚举长度len
    枚举起点i
        计算终点j
        枚举中点k
            起点到中点的check
                中点到终点的check
                    转移

字符不多,所以是可以跑过去的

代码

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

int le[5], f[211][211][5];
bool z[5][5][5], flag;
char yuan[5], s[5], ss[211];

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

int main() {
    strcpy(yuan, " WING");
    for(int i = 1; i <= 4; i++) le[i] = read();
    for(int i = 1; i <= 4; i++) {
        for(int j = 1; j <= le[i]; j++) {
            scanf("%s", &s);
            z[i][calc(s[0])][calc(s[1])] = 1;
        }
    }
    scanf("%s", ss + 1);
    int n = strlen(ss + 1);
    for(int i = 1; i <= n; i++) f[i][i][calc(ss[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 ip = 1; ip <= 4; ip++) {
                    if(f[i][k][ip]) {
                        for(int jp = 1; jp <= 4; jp++) {
                            if(f[k + 1][j][jp]) {
                                for(int kp = 1; kp <= 4; kp++) {
                                    if(z[kp][ip][jp] == 1) {
                                        f[i][j][kp] = 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    for(int i = 1; i <= 4; i++) {
        if(f[1][n][i]) {
            flag = 1;
            printf("%c", yuan[i]);
        }
    }
    if(!flag) cout << "The name is wrong!\n";
    return 0;
}

转载于:https://www.cnblogs.com/loceaner/p/11446702.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值