某人有一套玩具,并想法给玩具命名。首先他选择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] \to 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;
}
原文地址:https://www.cnblogs.com/mollnn/p/12426216.html
时间: 2024-10-10 04:58:40