题目大意
第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。
接下来W行,每行两个字母,表示W可以用这两个字母替代。
接下来I行,每行两个字母,表示I可以用这两个字母替代。
接下来N行,每行两个字母,表示N可以用这两个字母替代。
接下来G行,每行两个字母,表示G可以用这两个字母替代。
最后一行一个长度不超过Len的字符串。表示这个玩具的名字。
做法
我们把WING映射为1234
区间
d
p
dp
dp,我们用dp
[
l
]
[
r
]
[
k
]
[l][r][k]
[l][r][k]代表区间[l,r]能否合成k,若可以
d
p
[
l
]
[
r
]
[
k
]
dp[l][r][k]
dp[l][r][k]为
1
1
1,否则为0.
我们用三维数组 c h [ i ] [ j ] [ k ] ch[i][j][k] ch[i][j][k]来代表i是否可以由 j , k j,k j,k合成。
这样我们可以用时间复杂度 O ( 4 3 ∗ l e n 2 ) O(4^3*len^2) O(43∗len2)来解决这题。
具体是枚举断点的时侯枚举三个值 k 1 , k 2 , k 3 k1,k2,k3 k1,k2,k3代表 k 1 k1 k1为左区间合成的数, k 2 k2 k2代表右区间合成的数, k 3 k3 k3枚举 k 1 , k 2 k1,k2 k1,k2所能合成的数。
记得先初始化长度为1的区间。
#include<bits/stdc++.h>
using namespace std;
char s[] = "WING";
int a[4];
bool ch[5][5][5];
int Find(char t) {
for(int i = 0; i < 4; i++) {
if(t == s[i]) return i + 1;
}
return 0;
}
bool dp[205][205][5];
int main() {
string t;
for(int i = 0; i < 4; i++) cin >> a[i];
for(int i = 0; i < 4; i++) {
for(int j = 0; j < a[i]; j++) {
cin >> t;
ch[i+1][Find(t[0])][Find(t[1])] = 1;
}
}
cin >> t;
int n = t.size();
for(int i = 0; i < n; i++) dp[i][i][Find(t[i])] = 1;
for(int len = 1; len < n; len++) {
for(int l = 0; l + len < n; l++) {
int r = l + len;
for(int k1 = 1; k1 <= 4; k1++) {
for(int k2 = 1; k2 <= 4; k2++) {
for(int d = l; d < r; d++) {
if(dp[l][d][k1] && dp[d+1][r][k2]) {
for(int k3 = 1; k3 <= 4; k3++) {
dp[l][r][k3] |= ch[k3][k1][k2];
}
}
}
}
}
}
}
int f = 0;
for(int i = 1; i <= 4; i++) {
if(dp[0][n-1][i]) cout << s[i-1], f = 1;
}
if(!f) cout << "The name is wrong!";
}