P4290 [HAOI2008] 玩具取名(区间dp,传递闭包?)

link

有点传递闭包的思想感觉这题(无聊倒装

首先为了便于处理,将 W,I,N,G 映射为 1,2,3,4

那么处理数据,想到可以用 传递闭包 的思想?感觉差不多,因为这道题有很多一一对应的关系,并且可以由小的对应关系得到大的对应关系

对于每次输入对应的两个字符 ab,定义 g[a,b,i]{0,1} 表示对应关系


题目要求给定一个串 s 和一些对应关系,最终可以转化为哪几个单个字符,相当于我们知道单个字符的对应双字符,然后看看能不能对应上整个 s,从小区间推到大区间,考虑 区间dp

定义 f[l,r,x]{0,1}, x{1,2,3,4} 表示区间 [l,r] 是否可以被“字符”x 替换掉,也就是对应上

引入中间值 k,将区间分而治之拆分成 f[l,k,?]f[k+1,r,?]

两个小区间的第三维度?想到 一个字符总是对应两个字符,所以另外两个字符也要分别枚举,不过要能转移的条件肯定要 另外两个字符能对应 x,即:

f[l,r,x]=f[l,r,x] | (f[l,k,y] & f[k+1,r,z] & g[y,z,x])

哦对了,注意边界初始化,对于区间 [i, i],它肯定能被 i 上的字符替换

忽略枚举 x,y,z 的常数,还是 O(n3)

#include <bits/stdc++.h>
#define re register int
using namespace std;
const int N = 210;
int n, s[5], mat[N];
int g[5][5][5], f[N][N][5];
char t[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
mat['W'] = 1, mat['I'] = 2, mat['N'] = 3, mat['G'] = 4;
for (re i = 1; i <= 4; i ++) cin >> s[i];
for (re i = 1; i <= 4; i ++)
for (re j = 1; j <= s[i]; j ++)
{
string c; cin >> c;
g[mat[c[0]]][mat[c[1]]][i] = 1;
}
string tt; cin >> tt;
n = tt.size();
for (re i = 0; i < n; i ++) t[i + 1] = tt[i];
for (re i = 1; i <= n; i ++) f[i][i][mat[t[i]]] = 1;
for (re len = 1; len <= n; len ++)
for (re l = 1; l + len - 1 <= n; l ++)
{
int r = l + len - 1;
for (re k = l; k < r; k ++)
for (re x = 1; x <= 4; x ++)
for (re y = 1; y <= 4; y ++)
for (re z = 1; z <= 4; z ++)
f[l][r][x] = f[l][r][x] | (f[l][k][y] & f[k + 1][r][z] & g[y][z][x]);
}
bool flag = false;
if (f[1][n][1]) { flag = true; cout << 'W'; }
if (f[1][n][2]) { flag = true; cout << 'I'; }
if (f[1][n][3]) { flag = true; cout << 'N'; }
if (f[1][n][4]) { flag = true; cout << 'G'; }
if (!flag) cout << "The name is wrong!";
cout << '\n';
return 0;
}
posted @   Zhang_Wenjie  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示