• HDU 1565 方格取数(简单状态压缩DP)


    http://acm.hdu.edu.cn/showproblem.php?pid=1565

    对于每一个数,取或者不取,用0表示不取,1表示取,那么对于每一行的状态,就可以用一个二进制的数来表示。比如5的二进制为101,就表示取第一个数,不取第二个数,取第三个数。

    将符合要求的状态保存下来,什么是符合要求的呢?即二进制数中不存在相邻的1(110,011都是不符合要求的)。可以用移位并按位与的办法来判断,举个例子:110左移一位为011 ,110&011 = 1,不符合要求;101左移一位为010,101&010=0,符合要求,这是判断同一行时的方法。

    判断上下两行,只需将上下两行的状态按位与即可。(PS:在纸上写写,和容易就能看出来)

    然后枚举每一行的状态和上一行的状态,找出不与上一个状态冲突的情况,然后计算,选择当前状态的最大值

    AC

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    int status[20000];//存状态
    int mp[25][25];
    int d[25][20000];//d[i][j]表示第i行第j种状态时的最大和(这时的最大和是1~i行所能取得的最大和)
    int n;
    ///将符合要求的状态保存下来,即没有两个一相邻的情况
    int init(int n)
    {
        int M=0;
        for(int i=0 ; i<n ; i++)
        if((i&(i>>1))==0)///不相邻
        status[M++] = i;
        return M;
    }
    ///计算该状态的和
    int cal(int x,int t)
    {
        int sum=0,j=n-1;
        while(t)
        {
            if(t&1)///最后为是1
            sum+=mp[x][j];
            j--;
            t >>= 1;
        }
        return sum;
    }
    int main( )
    {
    
        while(scanf("%d",&n)!=EOF)
        {
             if(n == 0)//加上这句用C++提交能过,没这句C++就过不了,但G++能,不知道为啥
            {
                printf("0
    ");
                continue;
            }
            int M = init(1<<n);///初始化,找到状态一有多少
            memset(d,0,sizeof(d));
            for(int i=0 ; i<n ; i++)
            for(int j=0 ; j<n ; j++)
            scanf("%d",&mp[i][j]);
            for(int i=0 ; i<M ; i++)
            d[0][i]=cal(0,status[i]);
            for(int i=1 ; i<n ; i++)///第i行
            {
                for(int j=0 ; j<M ; j++)///枚举第i行状态
                {
                    int t=cal(i,status[j]);
                    for(int k=0 ; k<M ; k++)///枚举上一行的状态,即第i-1行  
                    {
                        if(status[j]&status[k])///上一行和这一行存在上下相邻的1 
                        continue;
                        d[i][j]=max(d[i-1][k]+t,d[i][j]);
                    }
                }
            }
            int ans=0;
            for(int i=n-1 , j=0 ; j<M ; j++)
                ans=max(d[i][j],ans);
            printf("%d
    ",ans);
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    给窗体加个圣诞帽——抛砖引玉
    《高手寂寞》随感
    离职日记-计划与变化
    什么样的生活
    这一年……
    写在2011第一天的工作前
    Visual C++ 学习笔记四 —— 模板
    bugfree安装与配置
    QTP环境变量的使用
    测试提问单[转]
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9132788.html
Copyright © 2020-2023  润新知