hdu 2167 状态压缩dp

来源:互联网 发布:mac浏览器开发者模式 编辑:程序博客网 时间:2024/06/06 20:19
/*状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]);*/#include<stdio.h>#include<string.h>#define N   16int ma[N][N];int num[N];char s[150];int lower[15];//储存二级制int dp[N][1<<N];//储存最优状态int now[1<<N],cu;//储存合法的状态int sum[N][1<<N];//储存第i行第j个状态的总的权值和int Max(int a,int b){    return a>b?a:b;}int main(){    int n,i,j,k,maxx;    lower[0]=1;    for(i=1; i<=15; i++)        lower[i]=lower[i-1]*2;    while(gets(s))    {        k=0;        j=0;        n=0;        for(i=0; s[i]; i++)        {            if(j&&s[i]==' ')            {                ma[1][++n]=k;                j=0;                k=0;            }            if(s[i]>='0'&&s[i]<='9')            {                k=k*10+s[i]-'0';                j=1;            }        }        if(j)            ma[1][++n]=k;        for(i=2; i<=n; i++)            for(j=1; j<=n; j++)                scanf("%d",&ma[i][j]);        cu=0;        for(i=0; i<(1<<n); i++)//储存合法的状态        {            if(i<<1&i)continue;            now[++cu]=i;        }        memset(sum,0,sizeof(sum));        memset(dp,0,sizeof(dp));        for(i=1; i<=n; i++)            for(j=1; j<=cu; j++)                for(k=0; k<n; k++)//因为在二进制中1代表的就是lower[0],如果k从1开始的话,lower[1]=2,就缺少了1的情况                    if(lower[k]&now[j])sum[i][j]+=ma[i][k+1];//lower[k]才是有效地        for(i=1; i<=cu; i++)//初始化第一行            dp[1][i]=sum[1][i];        for(i=2; i<=n; i++)            for(j=1; j<=cu; j++)                for(k=1; k<=cu; k++)                {                    if(now[j]&now[k])continue;                    if(now[j]&(now[k]<<1))continue;//如果和对角线和上面都没有相邻就符合                    if(now[j]&(now[k]>>1))continue;                    dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]);                }        maxx=-1;        for(i=1; i<=cu; i++)//求出所有状态的最大值            if(maxx<dp[n][i])                maxx=dp[n][i];        printf("%d\n",maxx);        gets(s);        gets(s);    }    return 0;}

0 0
原创粉丝点击