zoukankan      html  css  js  c++  java
  • BZOJ 1725: [Usaco2006 Nov]Corn Fields牧场的安排 状压动归

    Description

    Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地。FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。当然,FJ还没有决定在哪些土地上种草。 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮FJ算一下这个总方案数。

    Input

    * 第1行: 两个正整数M和N,用空格隔开

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

    Output

    * 第1行: 输出一个整数,即牧场分配总方案数除以100,000,000的余数

    题解: 

    状压动归傻题.

    保存有用状态来减少枚举的状态数.

    Code:

    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define mod 100000000
    #define maxn 20 
    #define ll long long 
    using namespace std;      
    ll F[15][20000],ans; 
    int G[20][20],w[20]; 
    vector<int>sta[maxn],h; 
    int main(){
        // setIO("input"); 
        int n,m; 
        scanf("%d%d",&n,&m); 
        for(int i=1;i<15;++i) w[i]=(1<<(i-1)); 
        //预处理出所有合法状态 
        for(int k=0;k<w[m+1];++k)
        {
            int l=k,pre=0,flag=1; 
            while(l)
            {
                if((l&1) && pre) { flag=0; break; }
                if(l&1) 
                    pre = 1;  
                else 
                    pre = 0; 
                l>>=1; 
            }
            if(flag) h.push_back(k); 
        }
        for(int i=1;i<=n;++i)
        {
            int cur=0; 
            for(int j=1;j<=m;++j) 
            {
                scanf("%d",&G[i][j]);               
                if(G[i][j]==0) cur|=w[j];    //不合法
            }        
            for(int j=0,sz=h.size();j<sz;++j) 
            {
                if(h[j]&cur) continue; 
                sta[i].push_back(h[j]); 
            }
        }
        F[1][0]=1; 
        for(int i=0,sz=sta[1].size();i<sz;++i) F[1][sta[1][i]]=1; 
        for(int i=2;i<=n;++i)
        {
            for(int j=0,sz=sta[i].size();j<sz;++j) 
            {                        
                for(int k=0,sz2=sta[i-1].size();k<sz2;++k){
                    if(sta[i][j]&sta[i-1][k]) continue; 
                    F[i][sta[i][j]]=(F[i][sta[i][j]]+F[i-1][sta[i-1][k]])%mod; 
                } 
            }
        }         
        for(int i=0,sz=sta[n].size();i<sz;++i) ans=(ans+F[n][sta[n][i]])%mod;             
        printf("%lld",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    tricky c++ new(this)
    MCI使用
    LoadIcon的使用
    深入浅出Node.js (2)
    洛谷 P1464 Function
    洛谷 P1722 矩阵 II
    洛谷 P1036 选数
    洛谷 P1303 A*B Problem
    洛谷 P2694 接金币
    洛谷 P1679 神奇的四次方数
  • 原文地址:https://www.cnblogs.com/guangheli/p/10948273.html
Copyright © 2011-2022 走看看