点击这里查看原题
比HDU1565更复杂的一道状压DP,需要多记录一位左上角的情况。每次换行的时候不需要考虑左上角,但是需要将每一位左移一位
图转自http://blog.csdn.net/sf____/article/details/15026397
/*
User:Small
Language:C++
Problem No.:2167
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
int n,p,q,tot,t,a[20][20];
ll f[2][1<<16],ans;
int main(){
freopen("data.in","r",stdin);//
ios::sync_with_stdio(false);
while(1){
memset(f,-1,sizeof(f));
p=0,q=1;
n=16;
t=0;
f[q][0]=0;
//读入
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
char ch;
if(scanf("%d%c",&a[i][j],&ch)==-1) return 0;
t++;
if(ch=='\n'&&n==16) n=t;
}
}
tot=1<<n+1;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
swap(p,q);
memset(f[q],-1,sizeof(f[q]));
for(int s=0;s<tot;s++){
if(~f[p][s]==0) continue;
if(j==0){//如果换行,此时无需考虑左上角,直接抛弃最高位
int ss=(s<<1)&(~(1<<(n+1)));
f[q][ss&(~1)]=max(f[q][ss&(~1)],f[p][s]);
if(!(s&(1<<j))&&!(s&(1<<j+1)))
f[q][ss^(1<<j)]=max(f[q][ss^(1<<j)],f[p][s]+a[i][j]);
continue;
}
//不取
f[q][s&(~(1<<j))]=max(f[q][s&(~(1<<j))],f[p][s]);
if(!(s&(1<<j))&&!(s&(1<<(j+1)))&&!(s&(1<<(j-1)))&&!(s&(1<<(j+2))))//j-1为上一位,j为左上角,j+1为本位,j+2为下一位
f[q][s^(1<<j)]=max(f[q][s^(1<<j)],f[p][s]+a[i][j]);
}
}
}
ans=0;
for(int s=0;s<tot;s++) ans=max(ans,f[q][s]);
printf("%lld\n",ans);
}
return 0;
}