zoukankan      html  css  js  c++  java
  • poj 3254(状态压缩+动态规划)

    http://poj.org/problem?id=3254

    题意:有一个n*m的农场(01矩阵),其中1表示种了草可以放牛,0表示没种草不能放牛,并且如果某个地方放了牛,它的上下左右四个方向都不能放其他的牛,

    问总共有多少种放牛方案??(不放也是一种方案)

    状态压缩讲的好的博客

    分析:利用状态压缩进行求解,先筛选出每行所有的可能状态,然后将每行与所有可行状态进行比较。

    dp[i][j]表示当第i行的状态为j时前i行的放牛方案总数。

    所以状态转移方程便是 dp[i][j] = dp[i][j]+dp[i-1][t] //t代表第i-1行所有符合条件的状态数。

    最后的结果为 sum(dp[n][i]) ..数组开小了,不停WA

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define N 12
    #define mod 100000000
    using namespace std;
    int dp[N+1][1<<N];  ///dp[i][j]表示当第i行的状态为j时前i行的放牛方案总数
    int state[1<<N]; ///保存所有的合法状态数
    int cur[N+1]; ///每一行的状态,注意这里保存的是0,因为当我们保存0时,如果某一状态与当前行相与不为0,那么
    ///就能判断出那个状态是不合法的(假设那个位置不应该种草,而它种了草)
    int n,m;
    bool check(int k){
        if(k&(k<<1)) return false;
        return true;
    }
    void init(int &k){
        for(int i=0;i<(1<<m);i++){
            if(check(i)) state[++k]=i;
        }
        //printf("%d
    ",k);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF){
            int k = 0;
            init(k);
            int num;
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                cur[i]=0;
                for(int j=1;j<=m;j++){
                    scanf("%d",&num);
                    if(num==0) cur[i]+=(1<<(j-1));
                }
            }
            for(int i=1;i<=k;i++){
                if(!(cur[1]&state[i])){
                    dp[1][i]=1;
                }
            }
            for(int i=2;i<=n;i++){
                for(int j=1;j<=k;j++){
                    if(cur[i]&state[j]) continue; ///枚举第i行的可行状态state[j]
                    for(int t = 1;t<=k;t++){
                        if(cur[i-1]&state[t]) continue; ///枚举第i-1行的可行状态state[t]
                        if(state[j]&state[t]) continue; ///判断相邻两行状态是否合法
                        dp[i][j] = (dp[i][j]+dp[i-1][t]+mod)%mod;
                    }
                }
            }
            int ans = 0;
            for(int i=1;i<=k;i++){
                ans = (ans+dp[n][i]+mod)%mod;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    六种简单易理解的排序算法
    leetcode-數組篇
    leetcode-字符串篇
    java8 Optional优雅非空判断
    md2all 简单实用
    zooleeper面试题
    深入理解 JVM锁 与 分布式锁
    redission 高性能分布式锁
    Java传统 定时任务
    关于Zookeeper
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5408732.html
Copyright © 2011-2022 走看看