P4290 [HAOI2008]おもちゃの名前
タイトル説明
誰かが命名のアイデアに玩具、おもちゃのセット。まず、基本的な名称のおもちゃとして任意の文字彼WING 4つの文字を選択します。自分の名前が非常に長い拡張できるように、彼はその後、自分の好み、「WING」の代わりに使用する任意の2文字のアルファベットのいずれかの名前に応じます。
今、彼は最初の数文字を超えるによって変形することができる一つの長い名前を推測することができたいと思います。
入力形式
4つの整数W、I、N、Gの最初の行 各文字は、2つのいくつかの文字に置き換えることができ表します。
二文字の次のW線、Wは、二つの文字に置き換えてもよい表します。
二文字の次のIラインは、私は2つの文字に置き換えてもよい表します。
二文字の次のNラインは、Nが2つの文字に置き換えてもよい表します。
行G次に、行ごとに2つの文字は、2つの文字を表し、Gに置き換えてもよいです。
レン文字列を超えない長さの最後の行。それはおもちゃの名前ことを示しています。
出力フォーマット
彼の文字列の名前は、文字の変形によって得ることができます。(注文WINGの出力)
出力のいずれかによって変形することができない文字の名前を取得する場合と、「名前が間違っています!」
サンプル入力と出力
入力#1
1 1 1 1
II
WW
WW
IG
IIII
出力#1
に
説明/ヒント
データの30%がレンを満たす<= 20、W、I、N、G <= 6
満足100%データレン<= 200、W、I、N、G <= 16
[思考]
DP範囲
文字列に長い文字列から
バック文字から2つの文字はマップで表すことができる
プレマッピングに対応するすべての文字を見て
W = 1、I = 2 、N = 3 = 4 G
コード、あなたのそれぞれがすることができる別のいくつかの方法で
都合の転送後に、i番目、j番目の彼の代替方法をマッピング
F(I、J、K)とすることができるが、
私は、で表されi番目、jはj番目の別のi番目を表し
ているものの文字で表すことができ、K 1及び2の2つだけの数字の代わりに2つの文字を
開始DPのような完了後
DP(i、j、k)は、
IからJまでの文字列に文字列を組み合わせることができ、私は間隔の左端点を示し、jは、区間の右端点を表し、kは
最初の初期化彼ら自身のそれぞれから初期化文字列のビットは、その位置に文字として合成することができ
、重いサイクル5、列挙内のコンテンツコード
4つの数字ではなく、アウトマージすることができる上に1から最後まで最後のテスト列、
第四の列挙に最初からすぐに出力される
順序翼に応じてあることを確認します
[完了コード】
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
using namespace std;
int num[5];
map<char,int> w;
int f[5][20][3];
bool dp[205][205][5];
char a,b;
char s[205] = "0";
int len;
char ans[10] = {"0WING"};
int main()
{
w['W'] = 1,w['I'] = 2,w['N'] = 3,w['G'] = 4;
for(int i = 1;i <= 4;++ i)scanf("%d",&num[i]);
for(int i = 1;i <= 4;++ i)
for(int j = 1;j <= num[i];++ j)
{
cin >> a >> b;
f[i][j][1] = w[a];
f[i][j][2] = w[b];
}
scanf("%s",s + 1);
len = strlen(s) - 1;
// cout << len << endl;
for(int i = 1;i <= len;++ i)dp[i][i][w[s[i]]] = 1;
for(int i = 2;i <= len;++ i)//枚举区间长度
for(int l = 1,r = l + i - 1;l <= len - i + 1;l ++,r ++)//枚举区间的左端点和区间的右端点
for(int j = 1;j < i;++ j)//总的区间拼出来的数是由哪两个分区间组合出来的,也就是两个区间的交界处
for(int k = 1;k <= 4;++ k)//枚举WING
for(int z = 1;z <= num[k];++ z)//WING能够被组合出来的方案
if(dp[l][l + j - 1][f[k][z][1]] && dp[l + j][r][f[k][z][2]])//可行
dp[l][r][k] = 1;//标记
int fg = 0;
for(int i = 1;i <= 4;++ i)
{
if(dp[1][len][i] == true)
{
fg = 1;
cout << ans[i];
}
}
if(fg == 0)
cout << "The name is wrong!" << endl;
return 0;
}