zoukankan      html  css  js  c++  java
  • 刷题总结——bzoj1725(状压dp)

    题目:

    题目描述

    Farmer John 新买了一块长方形的牧场,这块牧场被划分成 N 行 M 列(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地。

    FJ 打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地的感觉,于是 FJ 不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。当然,FJ 还没有决定在哪些土地上种草。

    作为一个好奇的农场主,FJ 想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮 FJ 算一下这个总方案数。

    输入格式

    第 1 行: 两个正整数 N 和 M ,用空格隔开 
    第 2..N+1 行: 每行包含 M 个用空格隔开的整数,描述了每块土地的状态。输入的第 i+1 行描述了第 i 行的土地。所有整数均为 0 或 1 ,是 1 的话,表示这块土地足够肥沃,0 则表示这块地上不适合种草。

    输出格式

    输出一个整数,即牧场分配总方案数除以 100,000,000 的余数。

    样例数据 1

    输入  [复制]

     
    2 3 
    1 1 1 
    0 1 0

    输出

    9

    备注

    【样例说明】
    土地情况如下:

    1 1 1
    0 1 0

    按下图把肥沃的各块土地编号:

    1 2 3
    0 4 0

    只开辟一块草地的话,有 4 种方案:选 1、2、3、4 中的任一块。
    开辟两块草地的话,有 3 种方案:13、14 以及 34。
    选三块草地只有一种方案:1、3、4。
    再加把牧场荒废的那一种,总方案数为 4+3+1+1=9 种。

    【数据范围】
    对于 50% 的数据,满足1≤N≤5;1≤M≤6
    对于 100% 的数据,满足1≤N≤12;1≤M≤12。

    题解:

    状压dp裸题,用dp[i][j]表示处理到第i行,第i行状态为j的方案数,dp[1][j]可以预处理出来,每次处理dp[i][k]时先枚举dp[i-1][j]是否符合条件,再看k和j是否符合条件(详细见代码)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int mod=1e8;
    const int N=15;
    int map[N],dp[N][5000],n,m,maxx,ans;
    void Dp()
    {
      for(int i=0;i<=maxx;i++)
        if((i&(i>>1))==0 && (i|map[1])==map[1])
          dp[1][i]=1; 
      for(int i=2;i<=n;i++)
        for(int j=0;j<=maxx;j++)
          if(dp[i-1][j])
            for(int k=0;k<=maxx;k++)
            {
              if((k&j)==0&&(k&(k>>1))==0&&(k|map[i])==map[i])
                dp[i][k]=(dp[i][k]+dp[i-1][j])%mod;
            }
      for(int i=0;i<=maxx;i++)      
        ans=(ans+dp[n][i])%mod;    
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      //freopen("a.out","w",stdout);
      int a;
      scanf("%d%d",&n,&m);
      for(int i=1;i<=n;i++)  
        for(int j=1;j<=m;j++)
        {
          scanf("%d",&a);
          map[i]=(map[i]<<1)+a;
        }
      maxx=1;
      for(int i=1;i<=m;i++)
        maxx=(maxx<<1);  
      maxx--;
      Dp();
      cout<<ans<<endl;
      return 0;
    }
  • 相关阅读:
    PAT (Basic Level) Practise 1013 数素数
    PAT (Basic Level) Practise 1014 福尔摩斯的约会
    codeforces 814B.An express train to reveries 解题报告
    KMP算法
    rsync工具
    codeforces 777C.Alyona and Spreadsheet 解题报告
    codeforces 798C.Mike and gcd problem 解题报告
    nginx + tomcat多实例
    MongoDB副本集
    指针的艺术(转载)
  • 原文地址:https://www.cnblogs.com/AseanA/p/7434630.html
Copyright © 2011-2022 走看看