【动态规划】 回文词

来源:互联网 发布:流程优化的建议 编辑:程序博客网 时间:2024/04/29 20:17
 From Zossin回文词  国际信息学奥林匹克竞赛 (IOI) 竞赛原题       描述 Description    回文词是一种对称的字符串——也就是说,一个回文词,从左到右读和从右到左读得到的结果是一样的。任意给定一个字符串,通过插入若干字符,都可以变成一个回文词。你的任务是写一个程序,求出将给定字符串变成回文词所需插入的最少字符数。
  比如字符串“Ab3bd”,在插入两个字符后可以变成一个回文词(“dAb3bAd”或“Adb3bdA”)。然而,插入两个以下的字符无法使它变成一个回文词。       输入格式 Input Format    第一行包含一个整数N,表示给定字符串的长度,3<=N<=5000
  第二行是一个长度为N的字符串,字符串由大小写字母和数字构成。        输出格式 Output Format  一个整数,表示需要插入的最少字符数。       样例输入 Sample Input         样例输出 Sample Output         时间限制 Time Limitation  各个测试点1s    

 

 

 

 

来源 Source

 

 

IOI 2000
by Zossin

 

 

用f[i,j]来表示将区间[i,j]里面的词变成回文串所需要的最小变化个数

显然此题可以由区间扩展而得来。

边界   f[i,i+1]:=0              //a[i]=a[i+1]

          f[i,i]:=0;

 

转移方程  f[i,j]:=      f[i+1,j-1]     //a[i]=a[j]

                           min(   f[i+1,j],   f[i,j-1]  )+1 

最后输出 f[1,n]

 

由于转移的顺序难以确定,我又写了个记忆化搜索。

var n,i,j:longint;    a:array[1..5000]of char;    f:array[0..5000,0..5000]of longint;function min(a,b:longint):longint;begin  if a>b then exit(b) else exit(a);end;function dp(i,j:longint):longint;begin    if f[i,j]<>-1 then exit(f[i,j]);    if (a[i]=a[j])and(i+1=j) then    begin        f[i,j]:=0;        exit(f[i,j]);    end;    if a[i]=a[j] then    begin       f[i,j]:=dp(i+1,j-1);       exit(f[i,j]);    end;        if a[i]<>a[j] then    begin      f[i,j]:=min(dp(i,j-1),dp(i+1,j))+1;      exit(f[i,j]);    end;end;begin    fillchar(f,sizeof(f),$7f);    readln(n);    for i:=0 to n-1 do for j:=i to n do f[i,j]:=-1;    for i:=1 to n do read(a[i]);    for i:=1 to n do f[i,i]:=0;    writeln(dp(1,n));    readln;readln;end.