| | | | 描述 Description | | | 回文词是一种对称的字符串——也就是说,一个回文词,从左到右读和从右到左读得到的结果是一样的。任意给定一个字符串,通过插入若干字符,都可以变成一个回文词。你的任务是写一个程序,求出将给定字符串变成回文词所需插入的最少字符数。 比如字符串“Ab3bd”,在插入两个字符后可以变成一个回文词(“dAb3bAd”或“Adb3bdA”)。然而,插入两个以下的字符无法使它变成一个回文词。 | | | |
| | | | 输入格式 Input Format | | | 第一行包含一个整数N,表示给定字符串的长度,3<=N<=5000 第二行是一个长度为N的字符串,字符串由大小写字母和数字构成。 | | | |
| | | | 输出格式 Output Format | | | 一个整数,表示需要插入的最少字符数。 | | | |
| | | | 时间限制 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. |