这道题有点像工程题的dp版本
特点就是比较繁琐
首先先枚举选取出来的行,列也行
然后定义状态f[i][j],表示前i列中选出j列时的最小分差和
然后状态转移即可
如果看不懂,说明基础不行,回去多补补题
#include<bits/stdc++.h>
using namespace std;
vector< vector<int> >gen(vector <vector<int> >matri,int row,int k){
int n=matri.size(),m=matri[0].size();
vector< vector<int> >res(row,vector<int>(m));
int inx=0;
for(int i=0;i<n;i++){
if((k>>i)&1){
for(int j=0;j<m;j++){
res[inx][j]=matri[i][j];
}
inx++;
}
}
return res;
}
bool check(int x,int r){
int cnt=0;
while(x){
if(x%2)cnt++;
x/=2;
}
return (cnt==r);
}
int solve(vector< vector<int> >matri,int c){
int n=matri.size(),m=matri[0].size();
int f[m+1][m+1];
for(int i=0;i<m+1;i++){
for(int j=0;j<m+1;j++){
f[i][j]=1e9;
}
}
int res=1e9;
for(int i=0;i<m;i++){
for(int j=1;j<=min(c,i+1);j++){
int tmp=0;
for(int r=0;r<n-1;r++)tmp+=abs(matri[r][i]-matri[r+1][i]);
// cout<<tmp<<endl;
if(j==1){
f[i][j]=tmp;
}
else {
for(int k=0;k<i;k++){
int tmp2=0;
for(int r=0;r<n;r++)tmp2+=abs(matri[r][i]-matri[r][k]);
f[i][j]=min(f[i][j],f[k][j-1]+tmp+tmp2);
}
}
if(j==c)res=min(res,f[i][j]);
}
}
return res;
}
int main(){
// freopen("1.txt","r",stdin);
int n,m,r,c;
cin>>n>>m>>r>>c;
vector< vector<int> >matri(n,vector<int>(m));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>matri[i][j];
}
}
int res=1e9;
for(int k=0;k<1<<n;k++){
if(!check(k,r)) continue;
vector< vector<int> >subm(r,vector<int>(c));
subm=gen(matri,r,k);
res=min(res,solve(subm,c));
// cout<<res<<endl;
}
cout<<res;
}