#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#define UP(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std;
const int INF=1000000000;
int g[25][25],f[25][25],dp[25][25],val[25][25];
int n,m,x,y,res;
int count(int a){
int x=0;
while(a){if(a&1)x++; a>>=1;}
return x;
}
void DP(){
UP(i,1,n)UP(j,i+1,n){
val[i][j]=0;
UP(k,1,y) val[i][j]+=abs(f[i][k]-f[j][k]);
}
UP(i,1,x)UP(j,i,n)dp[j][i]=INF;
UP(i,1,n){
dp[i][1]=0;
UP(j,2,y)dp[i][1]+=abs(f[i][j]-f[i][j-1]);
}
UP(i,2,x)UP(j,i,n)UP(k,i-1,j-1)
dp[j][i]=min(dp[j][i], dp[k][i-1]+val[k][j]+dp[j][1]);
UP(i,x,n) res=min(res, dp[i][x]);
}
int main(){
scanf("%d%d%d%d",&n,&m,&x,&y);
UP(i,1,n)UP(j,1,m)scanf("%d",&g[i][j]);
res=INF;
UP(i,0,(1<<m)-1){
if(count(i)!=y) continue;
int r=0;
UP(j,0,m-1){
if( ((i>>j)&1) ==0) continue;
++r;
UP(k,1,n) f[k][r]=g[k][j+1];
}
DP();
}
printf("%d\n",res);
return 0;
}
//穷举 60分
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define UP(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std;
const int INF=1000000000;
const int N=20;
int g[N][N],f[N][N],a[N][N],T;
int n,m,x,y,X=INF;
int count(int a){
int x=0;
while(a){if(a&1)x++; a>>=1;}
return x;
}
void Calc(){
int t=0;
UP(i,1,x)UP(j,1,y)t+=(abs(a[i][j]-a[i-1][j])+abs(a[i][j]-a[i][j-1]));
UP(i,1,x)t-=a[i][1];
UP(j,1,y)t-=a[1][j];
X=min(X,t);
}
int main(){
scanf("%d%d%d%d",&n,&m,&x,&y);
UP(i,1,n)UP(j,1,m)scanf("%d",&g[i][j]);
UP(i,0,(1<<m)-1){
if(count(i)!=y)continue;
int c=0;
UP(j,0,m-1){
if(((i>>j)&1)==0)continue;
++c; UP(k,1,n)f[k][c]=g[k][j+1];
}
UP(p,0,(1<<n)-1){
if(count(p)!=x)continue;
int r=0;
UP(q,0,n-1){
if(((p>>q)&1)==0)continue;
++r; UP(d,1,y)a[r][d]=f[q+1][d];
}
Calc();
}
}
printf("%d\n",X);
return 0;
}
var n,m,r,c,i,j,he,ans:longint; a,b:array[1..20,1..20] of longint; h,l:array[1..20] of longint; procedure qc; var i,j:longint; begin he:=0; for i:=1 to r do for j:=1 to c do begin if i+1<=r then he:=he+abs(b[i,j]-b[i+1,j]); if j+1<=c then he:=he+abs(b[i,j]-b[i,j+1]); end; end; procedure cl(x,k:longint); var i,j:longint; begin if x=c+1 then begin for i:=1 to r do for j:=1 to c do b[i,j]:=(a[h[i],l[j]]); qc; if ans>he then ans:=he; end; for i:=k to m do begin l[x]:=i; cl(x+1,i+1); end; end; procedure ch(y,k1:longint); var i:longint; begin if y=r+1 then cl(1,1); for i:=k1 to n do begin h[y]:=i; ch(y+1,i+1); end; end; begin readln(n,m,r,c); for i:=1 to n do for j:=1 to m do read(a[i,j]); ans:=maxlongint; ch(1,1); writeln(ans); end.
调试版
uses math; var a,b,s3,s4:array[0..20,0..20] of longint; s1,s2:array[0..20] of longint; i,j,m,n,r,c,ans:longint; procedure dfs(x,y:longint);//x作为第y列备选 var i,j,k,l:longint; begin s1[y]:=x; if y<r then for i:=x+1 to n do dfs(i,y+1) else begin fillchar(b,sizeof(b),0); for i:=1 to r do for j:=1 to m do b[i,j]:=a[s1[i],j]; fillchar(s2,sizeof(s2),0); for i:=1 to m do//每列各行差的和 for j:=1 to r-1 do inc(s2[i],abs(b[j+1,i]-b[j,i])); fillchar(s3,sizeof(s3),0); for i:=1 to m-1 do for j:=i+1 to m do//两列之间各行差值之和 for k:=1 to r do inc(s3[i,j],abs(b[k,i]-b[k,j])); fillchar(s4,sizeof(s4),$3f); for i:=0 to m do s4[i,0]:=0; for i:=1 to m do for j:=1 to min(c,i) do for k:=j-1 to i-1 do s4[i,j]:=min(s4[i,j],s4[k,j-1]+s2[i]+s3[k,i]); l:=999; for i:=1 to m do l:=min(l,s4[i,c]); if l=34 then begin for i:=0 to 5 do write(s1[i]:3); writeln;writeln; for i:=0 to 5 do write(s2[i]:3); writeln;writeln; for i:=0 to 5 do begin for j:=0 to 5 do write(s3[i,j]:3); writeln; end; writeln; for i:=0 to 5 do begin for j:=0 to 5 do write(s4[i,j]:13); writeln; end; halt; end; ans:=min(ans,l); end; end; begin readln(n,m,r,c); ans:=999; for i:=1 to n do for j:=1 to m do read(a[i,j]); dfs(0,0); //writeln(ans); end.
result
5 5 3 4 9 3 3 3 9 9 4 8 7 4 1 7 4 6 6 6 8 5 6 9 7 4 5 6 1 9 3 3 3 9 1 7 4 6 6 6 8 5 6 9 0 1 3 4 0 0 0 13 5 2 3 6 0 0 0 0 0 0 0 0 14 10 11 8 0 0 0 6 3 8 0 0 0 0 3 12 0 0 0 0 0 9 0 0 0 0 0 0 0 9999 9999 9999 9999 9999 0 13 9999 9999 9999 9999 0 5 32 9999 9999 9999 0 2 13 40 9999 9999 0 3 8 19 46 9999 0 6 18 23 34 61