# 【NOIP2014】子矩阵

dp[i][j]=min(dp[i][j],dp[k][j-1]+a[i]+b[k][i]);

a[i]表示 第i列选到的行的总差值

b[k][i]表示选到的每一行第k列和第i列之间的差值

 1 var
2   i,j,k,n,m,n1,m1,ans:longint;
3   dp,a,f:array[0..16,0..16] of longint;
4   hc:array[0..16,1..16,1..16] of longint;
5   b,lc:array[0..17] of longint;
6 function min(a,b:longint):longint;
7  begin
8   if a>b then min:=b
9          else min:=a;
10  end;
11 procedure ddp;
12  var
13   i,j,k,max:longint;
14  begin
15   fillchar(f,sizeof(f),0);
16   fillchar(lc,sizeof(lc),0);
17   fillchar(dp,sizeof(dp),0);
18   for i:=1 to m do
19    for j:=1 to n1-1 do
20     lc[i]:=lc[i]+abs(a[b[j+1],i]-a[b[j],i]);
21   for i:=1 to m do
22    for j:=i+1 to m do
23     for k:=1 to n1 do
24      f[i,j]:=f[i,j]+hc[b[k],i,j];
25   for i:=1 to m do
26    dp[i,1]:=lc[i];
27   for i:=2 to m do
28    for j:=2 to m1 do
29     if i>=j then
30               begin
31                dp[i,j]:=maxlongint;
32                for k:=j-1 to i-1 do
33                 dp[i,j]:=min(dp[i,j],dp[k,j-1]+lc[i]+f[k,i]);
34               end;
35   for i:=m1 to m do
36    if dp[i,m1]<ans then ans:=dp[i,m1];
37  end;
38 procedure jw(ii:longint);
39  begin
40   inc(b[ii]);
41   if ii>=0 then
42    if b[ii]>(n-n1+ii) then
43                          begin
44                           jw(ii-1);
45                           b[ii]:=b[ii-1]+1;
46                          end;
47  end;
48 begin
50   for i:=1 to n do
51    for j:=1 to m do
52     begin
54      for k:=1 to j-1 do
55       hc[i,k,j]:=abs(a[i,j]-a[i,k]);
56     end;
57   for i:=1 to n1 do
58    b[i]:=i;
59   ans:=100000000;
60   while b[0]=0 do
61    begin
62     ddp;
63     jw(n1);
64    end;
65   write(ans);
66 end.

posted @ 2016-09-13 19:11  JSC!  阅读(1483)  评论(0编辑  收藏  举报