题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167
思路:经典的状压dp题,前后,上下,对角8个位置不能取,状态压缩枚举即可所有情况,递推关系是为dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]),具体的含义见code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int s[1<<16]; 8 int sum[16][1<<16]; 9 int dp[16][1<<16]; 10 int map[16][16]; 11 int n,m,ans; 12 13 void Solve() 14 { 15 m=0; 16 for(int i=0;i<(1<<n);i++){ 17 if((i&(i<<1))==0)s[m++]=i;//所有合法的状态 18 } 19 memset(sum,0,sizeof(sum)); 20 memset(dp,0,sizeof(dp)); 21 for(int i=0;i<n;i++){ 22 for(int j=0;j<m;j++){ 23 for(int k=0;k<n;k++){ 24 if(s[j]&(1<<k))sum[i][j]+=map[i][k];//sum又来保存每一行的合法状态下的所有数的和 25 } 26 } 27 } 28 for(int i=0;i<m;i++)dp[0][i]=sum[0][i]; 29 for(int i=1;i<n;i++){ 30 for(int j=0;j<m;j++){ 31 for(int k=0;k<m;k++){ //上一行状态 32 if(s[j]&s[k])continue; 33 if(s[j]&(s[k]>>1))continue; 34 if(s[j]&(s[k]<<1))continue; 35 dp[i][j]=max(dp[i][j],dp[i-1][k]+sum[i][j]); 36 } 37 } 38 } 39 ans=0; 40 for(int i=0;i<m;i++){ 41 ans=max(ans,dp[n-1][i]); 42 } 43 printf("%d ",ans); 44 } 45 46 47 int main() 48 { 49 char str[111]; 50 while(gets(str)){ 51 int len=strlen(str); 52 n=0; 53 for(int i=0;i<len;i+=3){ 54 map[0][n++]=(str[i]-'0')*10+(str[i+1]-'0'); 55 } 56 for(int i=1;i<n;i++){ 57 int nn=0; 58 gets(str); 59 for(int j=0;j<len;j+=3){ 60 map[i][nn++]=(str[j]-'0')*10+(str[j+1]-'0'); 61 } 62 } 63 Solve(); 64 getchar(); 65 } 66 return 0; 67 } 68 69