50分后面的点大部分都A了不知道哪里有错误呢。。 大概思路就是,先枚举行再选列,选列用DP处理 Fij表示以i结尾(且必须选i)已经选了j列
code:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int MAXN = 50;
long long Lcnt,B[MAXN][MAXN],A[MAXN][MAXN],W[MAXN],sum[MAXN][MAXN],F[MAXN][MAXN];
int n,m,r,c;
long long ans;
//bool vis[MAXN];
void dfs(int line)
{
if(line == n + 1)return;
Lcnt++;
for(int i = 1;i <= m;i += 1)
B[Lcnt][i] = A[line][i];
if(Lcnt == r)
{
for(int i = 1;i <= m;i += 1)
{
W[i] = 0;
for(int j = 2;j <= r;j += 1)
W[i] += abs(B[j][i] - B[j - 1][i]);
}
for(int i = 1;i <= m;i += 1)
for(int j = i + 1;j <= m;j += 1)
{
for(int k = 1;k <= n;k += 1)
sum[i][j] += abs(B[k][i] - B[k][j]);
sum[j][i] = sum[i][j];
}
for(int i = 1;i <= m;i += 1)
{
F[i][1] = W[i];
for(int j = 2;j <= min(c,i);j += 1)
{
for(int k = j - 1;k < i;k += 1)
F[i][j] = min(F[i][j],F[k][j - 1] + sum[i][k]);
F[i][j] += W[i];
}
}
for(int i = c;i <= m;i += 1)
ans = min(ans,F[i][c]);
memset(F,0x7f7f7f7f,sizeof(F));
memset(sum,0,sizeof(sum));
}
else dfs(line + 1);
Lcnt--;
dfs(line + 1);
}
int main()
{
cin >> n >> m >> r >> c;
memset(F,0x7f7f7f7f,sizeof(F));
for(int i = 1;i <= n;i += 1)
for(int j = 1;j <= m;j += 1)
cin >> A[i][j];
ans = 1 << 10;
dfs(1);
cout << ans << endl;
return 0;
}