状态压缩 HDU 1565

多组数据

给你一个n*n的矩阵

不能相邻的取数 上下左右

求最大的和

#include<stdio.h>
#include<algorithm>
#include<string.h>

using namespace std;

int n;
int z[30][30];
int dp[2][1<<20+1],cnt; //dp和滚动数组差不多 推出的行只有相邻的有关系 
int num[20000];  //用来记录 合法的状态  就是同行要不相邻

int main()
{
    cnt=0;
    for(int i=0;i<(1<<20);i++)
        if((i&(i<<1))==0)
            num[cnt++]=i;

    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&z[i][j]);
        memset(dp,0,sizeof(dp));
        int len=(1<<n);

        for(int i=0;i<n;i++)
        {
            int p=i&1;       //奇数偶数
            for(int j=0;j<cnt;j++)
            {
                if(num[j]>=len)
                    break;
                int sum=0;
                for(int k=0;k<n;k++)  //和这个状态都是1 可以取
                {
                    if((num[j]&(1<<k)))
                        sum+=z[i][k];
                }
                int m1=0;
                for(int k=0;k<cnt;k++)
                {
                    if(num[j]>=len)
                        break;
                    if(!(num[j]&num[k]))  //上面最大的合法的状态转移过来
                        m1=max(m1,dp[1-p][num[k]]);
                }
                dp[p][num[j]]=sum+m1;  //本行加上面的
            }
        }
        int p=(n-1)&1;  //最后奇偶
        int ans=0;
        for(int i=0;i<len;i++) //最大的状态
            ans=max(dp[p][i],ans);
        printf("%d
",ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/cherryMJY/p/6128743.html