zoukankan      html  css  js  c++  java
  • POJ 3254

    Corn Fields
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 15745   Accepted: 8275

    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.

    Source

     
     

    今天刚学状压dp,碰到这个题,下午看了好几个博客,终于有了点头绪。(大佬的博客注释都比较少。。所以我写了比较多的注释)

    利用二进制与十进制的关系,降低维度。像这个题,每行的土地都只有0 1两种状态,可以把这一行的状态用一个十进制数表示。这应该就是一种状态压缩了~。
     
    题解:我们称一行中没有相邻的1的状态为好状态。。(不要在意名字)
    先将每行中所有的好状态找出来,用十进制表示,{   2的N次方 = (1<<(N-1) )   }
    void getvalid()///得到所有可行的状态
    {
        for(int i = 0 ; i < (1<<n);i++){
            if(!(i&(i<<1))){///如果这个数的二进制形式没有相邻的1,会将这个数记录下来
                st[num++] = i;
            }
        }
    }

    判断理想是否符合现实(该状态所对应的各个位置是否是肥沃土地)。

    bool judge(int p,int q)///判断该状态是否符合土地状况,也就是说,想种东西的地方是不是肥沃
    {
        if(!(st[p]&map[q])){///注意:!!这里土地状态map[q]是记录的不肥沃的土地,所以按位与后应为0,取非为1
            return true;    /// 换句话说 想法与实践比较,前者为想法,后者为实践,看是否可行
        }
        return false;
    }

    接下来更详细的在代码里都有了~~

    #include<iostream>
    #define MOD 100000000
    using namespace std;
    int dp[13][100005];///dp[i][j]表示第i行第j状态时的方案数
    int st[10009];///一行中所有的可行的状态
    int num;///记录状态数
    int n,m;///m行n列
    int s;///暂存单位土地的状态
    int map[15];///十进制数记录每行的土地状态
    
    void getvalid()///得到所有可行的状态
    {
        for(int i = 0 ; i < (1<<n);i++){
            if(!(i&(i<<1))){///如果这个数的二进制形式没有相邻的1,会将这个数记录下来
                st[num++] = i;
            }
        }
    }
    bool judge(int p,int q)///判断该状态是否符合土地状况,也就是说,想种东西的地方是不是肥沃
    {
        if(!(st[p]&map[q])){///注意:!!这里土地状态map[q]是记录的不肥沃的土地,所以按位与后应为0,取非为1
            return true;    /// 换句话说 想法与实践比较,前者为想法,后者为实践,看是否可行
        }
        return false;
    }
    int main()
    {
        cin >> m >> n;
        for(int i = 1 ; i <= m ; i++){
            map[i] = 0;
            for(int j = 1 ; j <= n ; j++){
                cin >> s;
                if(!s){
                    map[i] += (1<<(j-1));///将每行的不肥沃的土地记录下来
                }                       ///注意此处是j!!
            }
        }
    
        for(int i = 0 ; i < 13;i++){
            for(int j = 0 ; j < 100005;j++){
                dp[i][j] = 0;
            }
        }
        dp[0][0] = 1;///啥也不放时,算一种方案
        num = 0;
        getvalid();
    
        for(int i = 1 ; i <= m;i++){
            for(int j = 0; j < num ; j++){///j是这一行状态的编号
                if(judge(j,i)){
                    for(int k = 0 ; k < num ; k++){///k是这一行的编号
                        if(judge(k,i-1)&&!(st[j]&st[k])){///如果上一行的k对应的状态是“理想”与“现实”相同的  &  &  并且这一行状态与上一行状态之间没有出现相同位都是1
                            dp[i][j] += dp[i-1][k];
                        }
                    }
                }
            }
        }
    
        int sum = 0;
        for(int i = 0; i < num;i++){
            sum += dp[m][i];
            sum %= MOD;
        }
        cout << sum << endl;
    
    
        return 0;
    }
    
    

    转载请注明出处~~

    感谢您的阅读~

     
  • 相关阅读:
    DB2数据库查询过程(Query Processing)复合索引的匹配索引扫描(Matching Index Scans with Composite Indexs)
    DB2数据库查询过程(Query Processing)多索引访问(Multiple Index Access)
    Ubuntu 12.04(32位)安装Oracle 11g(32位)全过程以及几乎所有问题的解决办法
    消费者关注的 Win8 问题汇总(上)
    Surface Pro即将降临 上手体验先睹为快
    简于形 精于心 – 索尼 Duo 11上手体验
    消费者关注的 Win8 问题汇总(中)
    DPI 设置过大该如何还原?
    Ubuntu触摸板失灵
    Ubuntu下安装、配置git和gitflow
  • 原文地址:https://www.cnblogs.com/gudygudy/p/7245575.html
Copyright © 2011-2022 走看看