这题看上去没啥思路,一看数据范围小的可怜,就算了下暴搜的时间复杂度O(C(16,8)?(C(16,8)+m3))≈108似乎没啥问题,然后就写了个暴搜,出了点数据发现T了,又加了个剪枝然后就A了。。
结果一看人家的代码全是DP。。让我有点蛋疼。
其实只要把暴搜的后半部分一改就可以了,把二维压成一维后,就有一个显然的DP方程:处理出选一列的代价lsi,选一对列的代价hs(i,j),设f(i,j)为选第i列,在第i列之前已经选了j-1列的最小代价,则显然
f(i,j)=lsi+min1≤k<i{ f(k,j?1)+hs(k,i) }
这道题虽然是普及组的题,但是也挺好的,让我明白把二维压到一维与直接在二维上做的巨大差别!这种思想以后我在处理矩阵的时候一定要时刻牢记!
Code(dfs):
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,r,c;
int a[20][20];
int ls[20],hs[20][20];
int list[20];
int ans=0x7fffffff;
inline void ldfs(int x,int last,int nowc,int nowsum){
if(m-x<nowc||nowsum>=ans)return;
if(x==m){
ans=min(ans,nowsum);
return;
}
ldfs(x+1,last,nowc,nowsum);
if(nowc)ldfs(x+1,x,nowc-1,nowsum+ls[x]+hs[last][x]);
}
inline void hdfs(int x,int now){
if(n-x<now)return;
if(x==n){
int i,j;
memset(ls,0,sizeof(ls));
for(i=m;i--;)
for(j=r;--j;)
ls[i]+=abs(a[list[j]][i]-a[list[j-1]][i]);
int k;
memset(hs,0,sizeof(hs));
for(i=0;i<m;++i)
for(j=i+1;j<m;++j)
for(k=r;k--;)
hs[i][j]+=abs(a[list[k]][i]-a[list[k]][j]);
ldfs(0,m-1,c,0);
return;
}
hdfs(x+1,now);
if(now){
list[--now]=x;
hdfs(x+1,now);
}
}
int main(){
freopen("submatrix.in","r",stdin);
freopen("submatrix.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&r,&c);
int i,j;
for(i=0;i<n;++i)
for(j=0;j<m;++j)
scanf("%d",a[i]+j);
hdfs(0,r);
printf("%d\n",ans);
}
Code(DP):
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,r,c;
int a[20][20];
int ls[20],hs[20][20];
int list[20];
int ans=0x7fffffff;
int f[20][20];
inline void ldfs(int x,int last,int nowc,int nowsum){
int i,j;
for(i=0;i<m;++i)
for(j=0;j<=c;++j)
f[i][j]=1E9;
for(i=0;i<m;++i)f[0][0]=0,f[i][1]=ls[i];
int k;
for(i=1;i<m;++i)
for(j=2;j<=c;++j){
for(k=0;k<i;++k)f[i][j]=min(f[i][j],f[k][j-1]+hs[k][i]);
f[i][j]+=ls[i];
}
for(i=0;i<m;++i)ans=min(ans,f[i][c]);
}
inline void hdfs(int x,int now){
if(n-x<now)return;
if(x==n){
int i,j;
memset(ls,0,sizeof(ls));
for(i=m;i--;)
for(j=r;--j;)
ls[i]+=abs(a[list[j]][i]-a[list[j-1]][i]);
int k;
memset(hs,0,sizeof(hs));
for(i=0;i<m;++i)
for(j=i+1;j<m;++j)
for(k=r;k--;)
hs[i][j]+=abs(a[list[k]][i]-a[list[k]][j]);
ldfs(0,m-1,c,0);
return;
}
hdfs(x+1,now);
if(now){
list[--now]=x;
hdfs(x+1,now);
}
}
int main(){
freopen("submatrix.in","r",stdin);
freopen("submatrix.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&r,&c);
int i,j;
for(i=0;i<n;++i)
for(j=0;j<m;++j)
scanf("%d",a[i]+j);
hdfs(0,r);
printf("%d\n",ans);
}
时间: 2024-10-24 00:08:07