zoukankan      html  css  js  c++  java
  • poj3254 状态压缩dp

    题意:给一个图,1是可以放,0是不能放,可以放的地方放的不能相邻,求所有情况

    题解:状压dp

    参考博客:http://www.tuicool.com/articles/JVzMVj

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<iomanip>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define pi acos(-1)
    #define ll long long
    #define mod 100000000
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define MIN(a,b) a<b ? a:b
    
    using namespace std;
    
    const double g=10.0,eps=1e-9;
    const int N=15,maxn=30,inf=1<<29;
    
    int n,m,top;
    int cur[N],state[1<<N];
    int dp[N][1<<N];//dp[i][j]是前i行,每行有前j种排列方式
    
    bool ok(int x)//判断x中是否有1相邻的状态
    {
        if(x & x<<1)return 0;
        return 1;
    }
    void init()
    {
        top=0;
        for(int i=0;i< 1<<n;i++)
            if(ok(i))
               state[++top]=i;//所有每行中的1不相邻的状态
    }
    bool fit(int x,int k)//判断状态x与第k行状态是否重合
    {
        if(x & cur[k])return 0;
        return 1;//不重合就是1
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
     //   cout<<setiosflags(ios::fixed)<<setprecision(3);
        while(cin>>m>>n){//m是行,n是列
            init();
            memset(dp,0,sizeof dp);
            for(int i=1;i<=m;i++)
            {
                cur[i]=0;
                int num;
                for(int j=1;j<=n;j++)
                {
                    cin>>num;
                    if(num==0)cur[i]+=(1 << (n-j));//cur记录每行的状态
                }
            }
            for(int i=1;i<=top;i++)
                if(fit(state[i],1))//如果状态与第一行无重合
                   dp[1][i]=1;
            for(int i=2;i<=m;i++)
            {
                for(int k=1;k<=top;k++)//i行的所有状态
                {
                    if(!fit(state[k],i))continue;
                    for(int j=1;j<=top;j++)//i-1行的所有状态
                    {
                        if(!fit(state[j],i-1))continue;
                        if(state[k]&state[j])continue;//上下有1相邻了
                        dp[i][k]=(dp[i][k]+dp[i-1][j])%mod;
                    }
                }
            }
            int ans=0;
            for(int i=1;i<=top;i++)
                ans=(ans+dp[m][i])%mod;
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    代理模式
    面向对象设计原则
    砝码破碎
    阿里EasyExcel使用
    IBM的OpenJ9
    java反射 (复习)
    DecimalFormat保留小数
    Object类
    SQLMAP用法
    SQL盲注之时间注入
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/6849180.html
Copyright © 2011-2022 走看看