[HAOI2008] 玩具取名 - 区间dp
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2008] 玩具取名 - 区间dp相关的知识,希望对你有一定的参考价值。
某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。(n leq 200)
Solution
老生常谈的区间 dp
设 (f[i][j][k]) 表示能否将 ([i,j]) 压成 (k) 这个字母,(g[i][j][k]) 表示 (i,j) 这两个字母能否合成 (k) 这个字母,则
[
f[i][k][p] and f[k+1][j][q] and g[p][q][l] o f[i][j][l]
]
边界 (f[i][i][?]=1)
暴力转移即可
#include <bits/stdc++.h>
using namespace std;
const int N = 205;
int f[N][N][4],g[4][4][4],n,a[N],m[4];
int tr(char c) {
if(c=='W') return 0;
if(c=='I') return 1;
if(c=='N') return 2;
if(c=='G') return 3;
}
signed main() {
string str;
for(int i=0;i<4;i++) cin>>m[i];
for(int i=0;i<4;i++) {
for(int j=1;j<=m[i];j++) {
cin>>str;
g[tr(str[0])][tr(str[1])][i]=1;
}
}
cin>>str;
n=str.length();
for(int i=1;i<=n;i++) a[i]=tr(str[i-1]);
for(int i=1;i<=n;i++) f[i][i][a[i]]=1;
for(int le=2;le<=n;le++) {
for(int i=1;i+le-1<=n;i++) {
int j=i+le-1;
for(int k=i;k<j;k++) {
for(int p=0;p<4;p++) {
for(int q=0;q<4;q++) {
for(int l=0;l<4;l++) {
f[i][j][l]|=f[i][k][p]&f[k+1][j][q]&g[p][q][l];
}
}
}
}
}
}
int flag = 0;
if(f[1][n][0]) cout<<"W", flag=1;
if(f[1][n][1]) cout<<"I", flag=1;
if(f[1][n][2]) cout<<"N", flag=1;
if(f[1][n][3]) cout<<"G", flag=1;
if(flag==0) cout<<"The name is wrong!"<<endl;
}
以上是关于[HAOI2008] 玩具取名 - 区间dp的主要内容,如果未能解决你的问题,请参考以下文章