• USACO 2006 November Gold Corn Fields /// 状压 oj23941


    题目大意:

    输入n m

    接下来n行m列

    0表示不能种玉米 1表示能

    要求种玉米位置的上下左右四连通区域不能种玉米

    输出方案数

    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.

     
    #include <bits/stdc++.h>
    #define MOD 100000000
    using namespace std;
    int mir[13],may[1<<12],dp[13][1<<12];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m))
        {
            int num=0;
            for(int i=0;i<(1<<m);i++)
                if((i&(i<<1))==0) may[num++]=i;
            /// 等于0说明符合条件 may[]保存所有可能放置
            /// 左移一位后,若不为0,说明有相邻两位同时为1
            /// 如 i 为011,则 i<<1 为110,(011&110) = 1
            
            memset(mir,0,sizeof(mir));
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                {
                    int tmp; scanf("%d",&tmp);
                    if(tmp==0) mir[i]|=1<<j; 
                    /// mir[]可理解为 i 行的镜像拓本
                }
                
            memset(dp,0,sizeof(dp));
            for(int i=0;i<num;i++)/// 枚举所有可能 判断与拓本是否可匹配
                if((mir[0]&may[i])==0) dp[0][may[i]]=1;
            /// 等于0说明may[i]为该行的可能放置
                
            for(int i=0;i<n-1;i++) // 枚举各行 从本行推下一行 所以只需到n-1行
                for(int j=0;j<num;j++) // 枚举所有可能放置
                    if((mir[i]&may[j])==0)/// 当与本行可匹配时
                    { // 该放置是本行可能出现的符合条件的放置时
                        for(int k=0;k<num;k++)// 枚举所有可能(下一行的)
                            if(((mir[i+1]&may[k])==0)&&((may[k]&may[j])==0))
                            /// 该放置为下一行的可能放置(与下一行的拓本可匹配)
                            /// 且 与本行的放置可匹配时
                                dp[i+1][may[k]]+=dp[i][may[j]];
                    }
            int ans=0;
            for(int i=0;i<num;i++)// 枚举所有可能放置(最后一行)
                ans=ans+dp[n-1][may[i]],ans%=MOD; 
            // 由前往后推 所以只要最后一行存在这种放置的方案 
            // 则表示这种方案也符合前面所有行的放置
            printf("%d
    ",ans);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    自定义checkbox样式
    自定义select样式
    jsonp
    I/O复用 poll简介
    DOS和DDOS攻击
    TCP状态转换图解析
    Makefile入门
    I/O复用select 使用简介
    替换文本内容
    share memory
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9077930.html
Copyright © 2020-2023  润新知