1055: [HAOI2008]玩具取名

Description

某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
Input

第一行四个整数W、I、N、G。表示每一个字母能由几种两个字母所替代。接下来W行,每行两个字母,表示W可以用这两个字母替代。接下来I行,每行两个字母,表示I可以用这两个字母替代。接下来N行,每行两个字母,表示N可以用这两个字母替代。接下来G行,每行两个字母,表示G可以用这两个字母替代。最后一行一个长度不超过Len的字符串。表示这个玩具的名字。
Output

一行字符串,该名字可能由哪些字母变形而得到。(按照WING的顺序输出)如果给的名字不能由任何一个字母变形而得到则输出“The name is wrong!”
Sample Input
1 1 1 1
II
WW
WW
IG
IIII

Sample Output
IN

HINT

W可以变成II所以IIII可以缩成WW IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序输出IN [数据范围] 30%数据满足Len<=20,W、I、N、G<=6 100%数据满足Len<=200,W、I、N、G<=16

直接dp,f[i,j,k]表示i到j是否能表示成k(bool型的)

 1 const
 2     maxn=205;
 3 var
 4     num:array[1..4]of longint;
 5     w:array[1..4,0..30]of string;
 6     f:array[0..maxn,0..maxn,0..4]of boolean;
 7     len:longint;
 8 
 9 function calc(ch:char):longint;
10 begin
11     case ch of
12       'W':exit(1);
13       'I':exit(2);
14       'N':exit(3);
15       'G':exit(4);
16       else exit(0);
17     end;
18 end;
19 
20 function calc(ch:longint):char;
21 begin
22     case ch of
23       1:exit('W');
24       2:exit('I');
25       3:exit('N');
26       4:exit('G');
27       else exit(' ');
28     end;
29 end;
30 
31 procedure init;
32 var
33     i,j:longint;
34     s:char;
35     str:string;
36 begin
37     for i:=1 to 4 do
38       read(num[i]);
39     readln;
40     for i:=1 to 4 do
41       for j:=1 to num[i] do
42         readln(w[i,j]);
43     readln(str);
44     len:=length(str);
45     for i:=1 to len do
46       f[i,i,calc(str[i])]:=true;
47 end;
48 
49 procedure dp;
50 var
51     i,j,k,d,l,r:longint;
52 begin
53     for i:=1 to len-1 do
54       for j:=1 to len-i do
55         for k:=1 to 4 do
56           for d:=j to j+i-1 do
57             begin
58               for l:=1 to num[k] do
59                 if (f[j,d,calc(w[k,l][1])]) and (f[d+1,j+i,calc(w[k,l][2])]) then
60                 begin
61                   f[j,j+i,k]:=true;
62                   break;
63                 end;
64               if f[j,j+i,k] then break;
65             end;
66     for i:=1 to 4 do
67       if f[1,len,i] then write(calc(i));
68     for i:=1 to 4 do
69       if f[1,len,i] then exit;
70     write('The name is wrong!');
71 end;
72 
73 begin
74     init;
75     dp;
76 end.
View Code
原文地址:https://www.cnblogs.com/Randolph87/p/3654537.html