poj2531

来源:互联网 发布:js log函数 编辑:程序博客网 时间:2024/05/16 14:18

这题是dfs搜索+剪枝,20个结点共2^20中情况,暴力枚举时间复杂度O(2^20),485MS+136K,代码如下:

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 30int trim[Max][Max];bool top[Max];bool buttom[Max];int n;__int64 Count=0;void dfs(int index,__int64 ac){if(index==n+1){if(ac>Count)   Count=ac;return ;}    __int64 temp=ac;for(int i=1;i<index;i++)if(top[i])temp+=trim[index][i];top[index]=0;buttom[index]=1;dfs(index+1,temp);temp=ac;for(int i=1;i<index;i++)if(buttom[i])temp+=trim[index][i];buttom[index]=0;top[index]=1;dfs(index+1,temp);}int main(){scanf("%d",&n);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&trim[i][j]);memset(top,0,sizeof(top));memset(buttom,0,sizeof(buttom));dfs(1,0);printf("%I64d\n",Count);return 0;}


上面是纯暴力,没有任何剪枝,可以这样考虑,由于对称性,有一半的枚举情况是重复的,那么怎么样可以去掉那一半的枚举情况呢?这里,可以将1——n的某一个结点强制归为上方,这里取第一个结点归为上方,便于程序实现。这样就可以减少一半的枚举时间了,下面是代码: 235MS+136K

#include <stdio.h>#include <stdlib.h>#include <string.h>#define Max 30int trim[Max][Max];bool top[Max];bool buttom[Max];int n;__int64 Count=0;void dfs(int index,__int64 ac){if(index==n+1){if(ac>Count)   Count=ac;return ;}    __int64 temp=ac;for(int i=1;i<index;i++)if(top[i])temp+=trim[index][i];top[index]=0;buttom[index]=1;dfs(index+1,temp);temp=ac;for(int i=1;i<index;i++)if(buttom[i])temp+=trim[index][i];buttom[index]=0;top[index]=1;dfs(index+1,temp);}int main(){scanf("%d",&n);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&trim[i][j]);memset(top,0,sizeof(top));memset(buttom,0,sizeof(buttom));top[1]=1;buttom[1]=0;dfs(2,0);printf("%I64d\n",Count);return 0;}

网上有某牛可以在0ms的时间复杂度内解决。基本思路也是剪枝。

0 0
原创粉丝点击