【bzoj1055】 玩具取名 记忆化搜索

    这道题目可以用动态规划解决,为了方便起见用了记忆化搜索。在代码中,我把所有的字符全都转换成了数字便于后面的操作。不知道哪里写逗了结果跑得这么慢。。

    程序中用f[u][v][k]表示u..v这一段能否用编号为k的字母表示。-1表示尚未计算,0表示不行,1表示可以。具体的转移方程见代码。

下附AC代码:

const
  n=4;
  ans:array[1..4] of char=('W','I','N','G');
var
  c:array['A'..'Z'] of longint;
  p,q:array[0..n,0..20] of longint;
  a:array[0..n] of longint;
  b:array[0..210] of longint;
  f:array[0..210,0..210,0..4] of longint;
  i,j,len:longint; bo:boolean;
  ch1,ch2:char; s:string;
function dp(u,v,k:longint):longint;
var
  x,i:longint;
begin
  if f[u][v][k]<>-1 then exit(f[u][v][k]);
  if u=v then
    begin
      if b[u]=k then f[u][v][k]:=1
                else f[u][v][k]:=0;
      exit(f[u][v][k]);
    end;
  for x:=1 to a[k] do
    for i:=u to v-1 do
      if dp(u,i,p[k][x])+dp(i+1,v,q[k][x])=2 then
        begin
          f[u][v][k]:=1; exit(1);
        end;
  f[u][v][k]:=0;
  exit(0);
end;
begin
  fillchar(f,sizeof(f),255);
  c['W']:=1; c['I']:=2; c['N']:=3; c['G']:=4;
  for i:=1 to n do read(a[i]); readln;
  for i:=1 to n do
    for j:=1 to a[i] do
      begin
        readln(ch1,ch2);
        p[i][j]:=c[ch1]; q[i][j]:=c[ch2];
      end;
  readln(s); len:=length(s);
  for i:=1 to len do b[i]:=c[s[i]];
  bo:=true;
  for i:=1 to n do
    if dp(1,len,i)=1 then
      begin
        bo:=false; write(ans[i]);
      end;
  if bo then writeln('The name is wrong!');
end.


2015.2.8

by lych

你可能感兴趣的:(记忆化搜索)