1. 程式人生 > >USACO 2006 November Gold Corn Fields /// 狀壓 oj23941

USACO 2006 November Gold Corn Fields /// 狀壓 oj23941

是否 square span 說明符 輸入 lds memset ace sin

題目大意:

輸入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\n",ans); } return 0; }
View Code

USACO 2006 November Gold Corn Fields /// 狀壓 oj23941