bzoj 1055 [HAOI2008]玩具取名 区间dp

题面

题目传送门

解法

直接区间dp即可

时间复杂度:\(O(16n^3)\)

代码

#include <bits/stdc++.h>
#define N 210
using namespace std;
struct Node {
    int x, y;
} a[5][N];
int s[5], p[5][5][5];
bool f[N][N][5], vis[N][N][5];
int num(char ch) {
    if (ch == ‘W‘) return 1;
    if (ch == ‘I‘) return 2;
    if (ch == ‘N‘) return 3;
    return 4;
}
bool dp(int l, int r, int k) {
    if (r - l + 1 <= 2) return f[l][r][k];
    if (vis[l][r][k]) return f[l][r][k];
    vis[l][r][k] = 1;
    for (int i = l; i < r; i++)
        for (int j = 1; j <= s[k]; j++)
            f[l][r][k] |= (dp(l, i, a[k][j].x) & dp(i + 1, r, a[k][j].y));
    return f[l][r][k];
}
int main() {
    for (int i = 1; i <= 4; i++) cin >> s[i];
    for (int i = 1; i <= 4; i++)
        for (int j = 1; j <= s[i]; j++) {
            string st; cin >> st;
            p[num(st[0])][num(st[1])][i] = 1;
            a[i][j] = (Node) {num(st[0]), num(st[1])};
        }
    string st; cin >> st;
    int len = st.size() - 1;
    for (int i = 0; i <= len; i++) f[i][i][num(st[i])] = 1;
    for (int i = 0; i < len; i++)
        for (int j = 1; j <= 4; j++)
            f[i][i + 1][j] = p[num(st[i])][num(st[i + 1])][j];
    bool flag = false;
    for (int i = 1; i <= 4; i++) {
        f[0][len][i] = dp(0, len, i);
        if (!f[0][len][i]) continue;
        flag = true;
        if (i == 1) cout << ‘W‘;
        if (i == 2) cout << ‘I‘;
        if (i == 3) cout << ‘N‘;
        if (i == 4) cout << ‘G‘;
    }
    if (!flag) cout << "The name is wrong!\n";
    return 0;
}

原文地址:https://www.cnblogs.com/copperoxide/p/9476727.html

时间: 2024-10-10 04:58:44

bzoj 1055 [HAOI2008]玩具取名 区间dp的相关文章

[BZOJ 1055][HAOI2008]玩具取名(DP)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1055 分析: 比较难想的dp f[i][j][c]表示i..j能否压缩成字符c 那么怎么转移呢 如果存在i<=k<j,f[i][k][c1]=true且f[k+1][j][c2]=true且c1c2可以压缩成字符c(这个根据读入判断),那么f[i][j][c]就是true. 记忆化搜索比较好实现了.

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

1055: [HAOI2008]玩具取名 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1258  Solved: 729[Submit][Status][Discuss] Description 某 人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用 “WING”中任意两个字母代替,使得自己的名字能够扩充得很长.现在,他想请你猜猜某一个很长的名字,最初可能

BZOJ 1055 [HAOI2008]玩具取名

1055: [HAOI2008]玩具取名 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1119  Solved: 653[Submit][Status][Discuss] Description 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长.现在,他想请你猜猜某一个很长的名字,最初可能是由

[BZOJ 1055] [HAOI2008] 玩具取名 【记忆化搜索】

题目链接:BZOJ - 1055 题目分析 这种类似区间 DP 的记忆化搜索都是很相近的,比如字符串压缩和字符串扩展都差不多. 都是将现在 Solve 的区间分成子区间,再求解子区间. 这道题 Solve(l, r, x) 求能否将 [l, r] 的区间还原成 x ,那么就将它分成两段,看是否能左段变成 p , 右段变成 q. (x 能变成 pq) 代码 #include <iostream> #include <cstdio> #include <cstdlib> #

[HAOI2008] 玩具取名 - 区间dp

某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用"WING"中任意两个字母代替,使得自己的名字能够扩充得很长.现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的.\(n \leq 200\) Solution 老生常谈的区间 dp 设 \(f[i][j][k]\) 表示能否将 \([i,j]\) 压成 \(k\) 这个字母,\(g[i][j][k]\) 表示 \(i,j\)

【BZOJ】1055: [HAOI2008]玩具取名(dp)

http://www.lydsy.com/JudgeOnline/problem.php?id=1055 我竟然都没往dp这个方向想.....百度了下看到标题是dp马上就会转移了QAQ... 设d[i,j,k]表示i~j是否能转移成k. 那么很显然.. d[i,j,k]=d[i,k,x]&&d[k+1,j,y]&&a[k,x,y],a[k,x,y]表示k能转移到xy. 然后我数组小了re..(我都开了202啦........... 然后没有判误解wa了......太sb..

BZOJ 1055 HAOI2008 玩具取名 动态规划

题目大意:给定一个由'W','I','N','G'构成的字符串,给定一些规则,这些规则可以将两个字符合成为一个,例如"II"可以合成为'W',"WW"可以合成为'I'或者'N' 求这个字符串可以最终合成为哪几种字符 看到这题我想到了广搜...其实没必要,动归完全可以解决 令f[i][j][k]为从i开始的j个字符是否可以合成为字符[k] 然后j从外层循环,剩下的全部预处理,怎么暴力怎么转移,我写了六层循环,有点吓人 #include<cstdio> #i

【BZOJ-1055】玩具取名 区间DP

1055: [HAOI2008]玩具取名 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1560  Solved: 907[Submit][Status][Discuss] Description 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长.现在,他想请你猜猜某一个很长的名字,最初可能是由

bzoj1055: [HAOI2008]玩具取名(dp)

1055: [HAOI2008]玩具取名 题目:传送门 简要题意: 就是固定四个字母,给出这四个字母分别可以由哪两个字母组成,然后在给你一个字符串,要求把这个字符串还原成原始的四个字母的其中一个. 题解: 一开始看题有点瞎...想了想是一道超级大难题... 其实就是一个很简单的DP... 定义发f[i][j][s]:表示在字符串中i~j这个区间是否可以组合成为字符s 转移很容易就可以想出来:因为如果f[i][k][s1]==f[k+1][j][s2]==1(i<=k<=j) &&