• 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;
    }
  • 相关阅读:
    由当前acitivty直接退到桌面
    Android中SharedPreference多进程数据共享出错
    java回调机制
    Android 监听apk安装替换卸载广播
    jquery中如何退出each循环
    旋转六面体源码
    用CSS3制作的旋转六面体动画
    CSS中常用的字体单位:px、em、rem和%的区别
    css属性简写集合
    小游戏--别踩白块
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5408732.html
Copyright © 2020-2023  润新知