zoukankan      html  css  js  c++  java
  • POJ 3254 Corn Fields(状压DP)

    题目链接

    题意 : 一个m*n的矩形,1代表有草,0代表没有草,将牛放在有草的地方,牛与牛之间不能相邻。问有多少种方法。

    思路 : 状态压缩,从上往下枚举,如果第一行的确定了,那第二行中所有与第一行有草的地方相邻的格子便不能再用,以此类推,只要求出每行可用的方法数,dp[i][j] += dp[i-1][k]。代表的是第 i 行状态为 j 时,等于第i-1行状态为k时加上这一行的状态,当然,j与k中不能有相邻的1.所有的牛都不放也是一种方法,所以可以先对第一行预处理一下,状压时,对每一行的处理取反,后续处理方便。

     1 //3254
     2 
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <iostream>
     6 #include <cmath>
     7 #define mod 100000000
     8 
     9 using namespace std ;
    10 int dp[15][1 << 15],po[15] ;
    11 int mp[15][15],d[1 << 15] ;
    12 
    13 int main()
    14 {
    15     int n, m ;
    16     po[1] = 1 ;
    17     for(int i = 2 ; i <= 14 ; i++)
    18         po[i] = po[i-1] * 2 ;
    19     while(~scanf("%d %d",&m,&n))
    20     {
    21 // memset(dp,0,sizeof(dp)) ;
    22 //       memset(d,0,sizeof(d)) ;
    23 //        int s = m ;
    24         for(int i = 1 ; i <= m ; i++)
    25         {
    26             d[i] = 0 ;
    27             for(int j = 1 ; j <= n ; j++)
    28             {
    29                 scanf("%d",&mp[i][j]) ;
    30                 if(!mp[i][j])
    31                 d[i] += po[j] ;
    32             }
    33         }
    34 
    35         for(int i = 0 ; i < (1 << n) ; i++)
    36         {
    37             if((i >> 1) & i || (i << 1) & i)
    38                 continue ;
    39             if(i & d[1])
    40                 continue ;
    41             dp[1][i] = 1 ;
    42         }
    43         for(int i = 2 ; i <= m ; i++)
    44         {
    45             for(int j = 0 ; j < (1 << n) ; j++)
    46             {
    47                 if((j >> 1) & j || (j << 1) & j)//草地与不能左右草地相邻
    48                     continue ;
    49                 if((d[i] & j))//要枚举的方块必须是草地
    50                     continue ;
    51                 for(int k = 0 ; k < (1 << n) ; k++)
    52                 {
    53                     if((k << 1) & k || (k >> 1) & k)
    54                         continue ;
    55                     if((d[i-1] & k))
    56                         continue ;
    57                     if(! (j & k)){
    58                         dp[i][j] = (dp[i][j] + dp[i-1][k])%mod ;
    59                     }
    60                 }
    61             }
    62         }
    63         int sum = 0 ;
    64         for(int i = 0 ; i < (1 << n) ; i ++)
    65             sum = (sum + dp[m][i])%mod ;
    66         sum %= mod ;
    67         printf("%d
    ",sum) ;
    68     }
    69     return 0 ;
    70 }
    View Code
  • 相关阅读:
    WPF中样式中事件处理
    模板方法
    WPF 中ComboBox绑定DataSet
    装饰模式
    【转帖】c#项目的打包部署教材图文
    WPF中用比例设置长度或宽度
    在WFP中完美使用winform的控件
    一个WPF软件作品新鲜出炉,欢迎拍砖
    建造者模式(生成器模式)
    Windows Presentation Foundation 中的 Pack URI
  • 原文地址:https://www.cnblogs.com/luyingfeng/p/3893838.html
Copyright © 2011-2022 走看看