zoukankan      html  css  js  c++  java
  • POJ 3254 Corn Fields【状态压缩】

    Description

    Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can't be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.

    Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

    Input

    Line 1: Two space-separated integers: M and N 
    Lines 2..M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)

    Output

    Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.

    Sample Input

    2 3
    1 1 1
    0 1 0

    Sample Output

    9

    Hint

    Number the squares as follows:
    1 2 3
      4  

    There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.
     

    先说几句题外话:很感谢他(一大牛), 以一道题为例给我讲了一晚上,虽然那道题我还是没太明白,但是明显感觉我现在对于状态压缩开窍了,能看懂了,很感谢他...ORZ
    引用他给我讲的:就是有一些问题有很多状态,而这些状态的描述以及状态之间的关系能够用一个整形数简单的表示的话 ,那么就可以考虑用状压dp;
          状态压缩也是对空间可时间的一种优化;
    题目大意:0表示不能放牛,1表示可以放牛,但是牛与牛之间是不能挨着,共有多少种放置牛的方法;
    解题思路:将一行的状态表示为1 0 1二进制数字,即可化为一个整数代替;假设上一行(i-1行)状态为1 0 1(1表示放置牛) 那么他的下一行的合法状态有 0 0 0; 0 1 0;那么      对于第i行的状态至于上一行有关系即状态转移方程如下:dp[i][j]表示第i行状态为j时的数目;
          dp[i][j]=sum(dp[i-1][k]){k!=j, &&k属于对于i行的合法状态}

    代码如下:

    View Code
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<math.h> 
    using namespace std;
    #define N 13
    #define M 1<<N
    #define mod 100000000 
    int state[M], map[N], dp[N][M];  
    int judge1(int x)  
    {
        if(x&(x<<1))
            return 0;
        return 1;
    } 
    int judge2(int i, int k)  
    {
        if(map[i]&state[k])
            return 0;
        return 1; 
    }
    int main()
    {
        int i, j, m, n, a, tt, k, oknum;
        while(scanf("%d%d", &n, &m)!=EOF)
        {
            memset(map, 0, sizeof(map));
            memset(state, 0, sizeof(state));
            memset(dp, 0, sizeof(dp)); 
            for(i=1; i<=n; i++)
            {
                for(j=1; j<=m; j++)
                {
                    scanf("%d", &a);
                    if(a==0)
                        map[i]+=1<<(m-j);
                }
            }
            tt=(1<<m)-1; 
            oknum=0; 
            for(i=0; i<=tt; i++)
             {
                 if(judge1(i))
                     state[oknum++]=i;
            } 
            for(i=0; i<oknum; i++)
            { 
                if(judge2(1, i))
                    dp[1][i]=1;
            }
            for(i=2; i<=n; i++)
            {
                for(j=0; j<oknum; j++)
                {
                    if(!judge2(i, j)) 
                        continue;
                    for(k=0; k<oknum; k++)
                    {
                        if(!judge2(i-1, k))
                            continue;
                        if(!(state[j]&state[k])) 
                            dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
                    }
                }
            }
            int ans=0;
            for(i=0; i<oknum; i++)
                ans=(ans+dp[n][i])%mod;
            printf("%d\n", ans);
        }
    }
  • 相关阅读:
    Docker 学习4 Docker容器虚拟化网络概述
    Ceph 命令
    Day_09【常用API】扩展案例1_程序中使用一个长度为3的对象数组,存储用户的登录名和密码……
    Day_08【面向对象】扩展案例4_年龄为30岁的老王养了一只黑颜色的2岁的宠物……
    Day_08【面向对象】扩展案例3_使用多态的形式创建缉毒狗对象,调用缉毒方法和吼叫方法
    Day_08【面向对象】扩展案例2_测试旧手机新手机类,并给新手机实现玩游戏功能
    Day_08【面向对象】扩展案例1_测试项目经理类和程序员类
    用两个栈实现队列
    二叉树前序、中序、后序遍历相互求法
    洗牌
  • 原文地址:https://www.cnblogs.com/Hilda/p/2672747.html
Copyright © 2011-2022 走看看