• 状压学习笔记


      状态压缩利用二进制枚举每一种状态,用0和1表示取或不取,然后通过位运算实现。例如,现在有20个物品,分别用一个数在二进制下20位表示取或不取,例如,10在二进制下位1010,即代表选取第2和4个物品。对一个数x,判断第i个物品是否被选取可以用位运算(1<<i)&x判断。状态压缩通常伴随dp一起出现,是一种时间复杂度很高很暴力的算法。

      经典例题:hdu1565方格取数

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

      给一个n*n的方阵,取若干个数,要求任意两个数所在方格不相邻,求取出数的最大和。

      首先预处理出每行的取数方案,对于i,用1代表取,0代表不取,若(i>>1)&i为0,即代表i方案可以被选用,因为相邻两项不存在同为1的。

      然后对于每行,枚举该行选取方案,对上一行枚举方案枚举,若两方案与值为0则可以转移,因为此时没有同一列的被选取。自上而下转移即可。

      贴上AC代码。

      

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <int,int> pii;
    #define rep(i,x,y) for(int i=x;i<y;i++)
    #define rept(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define de(x) cout<< #x<<" = "<<x<<endl
    #define dd(x) cout<< #x<<" = "<<x<<" "
    #define mes(a,b) memset(a,b,sizeof a)
    const int inf= 0x3f3f3f3f;
    
    int way[1<<15],cnt=0;
    int matrix[25][25];
    
    int dp[25][1<<15];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        for(int i=0;i<(1<<20);i++)
            if((i&(i>>1))==0)
                way[cnt++]=i;
    //    de(cnt);
    //    de((1<<15));
        while(cin>>n)
        {
            mes(dp,0);
            rept(i,1,n)
                rept(j,1,n)
                    cin>>matrix[i][j];
            rept(i,1,n)
            {
                rep(j,0,cnt)
                {
                    if((1<<n)<=way[j]) break;
                    int sum=0,choose=way[j],p=1;
                    while(choose)
                    {
                        if(choose&1) sum+=matrix[i][p];
                        p++;
                        choose>>=1;
                    }
                //    dd(i);dd(j);de(sum);
                    dp[i][j]=0;
                    rep(k,0,cnt)
                    {
                        if((1<<n)<=way[k]) break;
                        if((way[j]&way[k])==0)
                        {
    //                        dd(j);de(k);
                            dp[i][j]=max(dp[i][j],dp[i-1][k]+sum);
                        }
                    }
                }
            }
            int ans=0;
            rep(i,0,cnt)
            {
        //        dd(i);
                if((1<<n)<=way[i]) break;
                ans=max(ans,dp[n][i]);
            }
            cout<<ans<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    js获取鼠标的位置
    去掉a标签的虚线框,避免出现奇怪的选中区域
    点击按钮 可以显示隐藏
    input标签获取焦点时文本框内提示信息清空背景颜色发生变化
    ie6下面不支持!important的处理方法
    [zz]【整理】Python中Cookie的处理:自动处理Cookie,保存为Cookie文件,从文件载入Cookie
    [vim]大小写转换
    [zabbix]zabbix2.0apt源安装
    [mysql]replace
    [ethernet]ubuntu更换网卡驱动
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/11910855.html
Copyright © 2020-2023  润新知