这道题的状态压缩简直匪夷所思(其实是我孤陋寡闻,而且我以前的博客竟然写了这题。。水啊)
嗯这题可以发现,我们可以用一个二进制表示一行的状态,1表示选0反之,可以发现行与行之间可选的范围是确定的,比如说:100这样的状态适用于每一行,推广一下:100001是适用于任何两行之间的。所以我们可以先将所有成立的状态求出来,要求就是左移一位和右移一位和原状态&运算为0,这样保证每个1左右都没有1。然后枚举行、状态,可以继承的状态,继承可以继承的状态的最大值,然后加上这一行的得到的值即可。
#include#include #include using namespace std;int n,mp[20][20];int ol,o[41000],f[20][41000];bool bj(int x,int y){ return ((x&y)==0)?true:false;}int hehe(int k,int x){ int tp=0,ans=0; while(x!=0) { tp++; if(x%2==1)ans+=mp[k][tp]; x/=2;if(tp==n)break; } return ans;}int main(){ scanf("%d",&n); int t=1;for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); t=t*2; } o[++ol]=0;f[1][0]=0; for(int i=1;i ans)ans=f[n][o[i]]; printf("%d\n",ans); return 0;}