题目:整理队形
题目描述
[问题描述]
学校艺术节上,规定合唱队要参加比赛,个个队员的衣服颜色不能很混乱:合唱队员应排成一横排,且衣服颜色必须是左右队称的。
例如:“红蓝绿蓝红”或“红蓝绿绿蓝红”都是符合的,而“红蓝绿红”或“蓝绿蓝红”就不符合。
合唱队的人数很多惊险有的同学就可能有3000个。老师希望将合唱队调整的符合要求,但要尽量调整的少,减少麻烦。仅有一下3种情况算作是一次调整:
1.在队伍中插入一个人;
2.剔掉一个人;
3.让一个人衣服换颜色。
老师想知道目前的队形下,调整的符合要求需要最少多少次操作。
因为合唱队很热门,所以你可以认为人数是无限的,即想加入一个人时,总有人加。同时衣服的颜色也是任意的。
输入格式
第一行是一个整数n(1<=n<=3000)
第二行是n个整数,从左到右表示现有的每个队员每个人的衣服颜色编号,都是不大于3000的自然数。
输出格式
一个数,即最少调整次数。
样例输入
样例输出
==============================
======================
{
ID:jie19952
PROG:
LANG:PASCAL
}
var
n:longint;
a,b:array[1..3000]of longint;
f:array[0..3000,0..3000]of longint;
procedure init;
begin
assign(input,'rq478.in');
assign(output,'rq478.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure main;
var
i,j,min:longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[i]);
b[n+1-i]:=a[i];
end;
fillchar(f,sizeof(f),$7);
for i:=0 to n do
begin
f[i,0]:=i;
f[0,i]:=i;
end;
min:=maxlongint;
f[0,0]:=0;
for i:=1 to n do
for j:=1 to n do
begin
if a[i]=b[j] then
begin
if f[i,j]>f[i-1,j-1] then
f[i,j]:=f[i-1,j-1];
end
else
begin
if f[i-1,j]+1<f[i,j] then f[i,j]:=f[i-1,j]+1;
if f[i,j-1]+1<f[i,j] then f[i,j]:=f[i,j-1]+1;
if f[i-1,j-1]+1<f[i,j] then f[i,j]:=f[i-1,j-1]+1;
end;
end;
writeln(f[n,n] div 2);
end;
begin
init;
main;
terminate;
end.