这题看上去没啥思路,一看数据范围小的可怜,就算了下暴搜的时间复杂度 O(C(16,8)∗(C(16,8)+m3))≈108 似乎没啥问题,然后就写了个暴搜,出了点数据发现T了,又加了个最优化剪枝然后就A了。。
结果一看人家的代码全是DP。。让我有点蛋疼。
其实只要把暴搜的后半部分一改就可以了,把二维压成一维后,就有一个显然的DP方程:处理出选一列的代价 lsi ,选一对列的代价 hs(i,j) ,设 f(i,j) 为选第i列,在第i列之前已经选了j-1列的最小代价,则显然
= =这里实际上还有一个问题,就是暴搜出所有组合的时间复杂度是多少。我们在n个数中选择m个,我们采用从前往后暴搜01串的搜索方式,并加上这样两个剪枝:如果当前搜出的1的个数大于m,剪枝;如果即使剩下的数的个数全选1也不足以凑齐m个,则剪枝。那么我们试图分析一下这两个剪枝的效果,第一个剪枝好说,第二个剪枝的话,我们考虑在还剩m-x个时它减掉的叶节点数目(要求它不能被还剩m-(x-1)时减掉),那么可以得到这样一个显然的式子:
#include
#include
#include
#include
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=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-xreturn;
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;ifor(j=i+1;jfor(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;ifor(j=0;jscanf("%d",a[i]+j);
hdfs(0,r);
printf("%d\n",ans);
}
Code(DP):
#include
#include
#include
#include
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;ifor(j=0;j<=c;++j)
f[i][j]=1E9;
for(i=0;i0][0]=0,f[i][1]=ls[i];
int k;
for(i=1;ifor(j=2;j<=c;++j){
for(k=0;k1]+hs[k][i]);
f[i][j]+=ls[i];
}
for(i=0;iinline void hdfs(int x,int now){
if(n-xreturn;
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;ifor(j=i+1;jfor(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;ifor(j=0;jscanf("%d",a[i]+j);
hdfs(0,r);
printf("%d\n",ans);
}