题目概述
多米诺骨牌有上下2个方块组成,每个方块中有1~6个点。现有排成行的n个骨牌,每个多米诺骨牌可以旋转180°,使得上下两个方块互换位置,求出最少的旋转次数使多米诺骨牌上下2行点数之差达到最小。
1<=n<=1000
解题思路
这题采用动态规划的思路,f[i,j]代表前i个骨牌能够组成差值为j的最小翻转次数,初始化最大值,f[0,0]=0;
状态转移方程为f[i,j]=min(f[i-1,j+a[i,3]+1,f[i-1,j-a[i,3]);(a[i,3]为第i个骨牌上下数字的差值)
注意边界,差值可能为负数。
时间复杂度:O(12000n)
空间复杂度:O(12000n)
源程序
vara:array[1..1002,1..3]of longint;
b:array[0..1002,-6006..6006]of integer;
i,n,sum1,sum2,j,t,ans,l:longint;
function minx(a,b:longint):longint;
begin
if a<b then exit(a)
else exit(b);
end;
begin
readln(n);
sum1:=0;
sum2:=0;
for i:=1 to n do
begin
readln(a[i,1],a[i,2]);
a[i,3]:=a[i,1]-a[i,2];
end;
fillchar(b,sizeof(b),$7f);
b[0,0]:=0;
for i:=1 to n do
begin
for j:=-6000 to 6000 do
b[i,j]:=minx(b[i-1,j+a[i,3]]+1,b[i-1,j-a[i,3]]);
end;
ans:=b[n,0];
l:=0;
if b[n,0]>10000 then
while l<6000 do
begin
inc(l);
if (b[n,l]<10000)and(ans>b[n,l]) then ans:=b[n,l];
if (b[n,-l]<10000)and(ans>b[n,-l]) then ans:=b[n,-l];
if (b[n,l]<10000)or(b[n,-l]<10000)then break;
end;
write(ans);
end.