Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 14230 | Accepted: 7460 |
Description
Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can't be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.
Input
Lines 2.. M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)
Output
Sample Input
2 3 1 1 1 0 1 0
Sample Output
9
Hint
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.
Source
题目链接:http://poj.org/problem?id=3254
我昨天晚上推了一晚上,然后就GG了,今早来了实验室看了大牛博客,恍然大悟,不得不说,大牛对位运算的操作已经登峰造极,炉火纯青了。
题目的意思是说有个农夫买了一块矩形的地分成小块要给他的牛种玉米,有一些小矩形并不能够种玉米,而且种玉米有一个规则就是种玉米的地不能够相邻。
放上大牛的链接吧,太厉害了:http://www.cnblogs.com/buptLizer/archive/2012/08/22/2650717.html
我就注释一下代码吧。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define mod 100000000
using namespace std;
const int MAXN=13;
const int MAXSTATE=(1<<12)+10;
int map1[MAXN][MAXN];
int ans[MAXSTATE];
int dp[MAXN][MAXSTATE];
int num,row,col;
void fax(){//这个函数是求在不管土地是否能够种玉米的情况下合法的状态
for(int i=0;i<(1<<col);i++){
if((i&(i<<1))==0){//不可相邻
ans[num++]=i;
}
}
}
bool judge(int state,int r){//判断state状态和第i行土地是否矛盾
int rstate=0;//第i行土地的状态
for(int i=1;i<=col;i++){
if(map1[r][i])
rstate+=(1<<(col-i));
}
if(!(state&(~rstate)))//仔细推敲一下这里的取反,大牛的位运算就是牛,想想看,如果不取反则有的情况则会矛盾
return true;
return false;
}
int main(){
while(~scanf("%d%d",&row,&col)){
memset(dp,0,sizeof(dp));
num=0;
for(int i=1;i<=row;i++){
for(int j=1;j<=col;j++){
scanf("%d",&map1[i][j]);
}
}
fax();
dp[0][0]=1;
for(int i=1;i<=row;i++){
for(int st=0;st<num;st++){//当前行的状态
if(judge(ans[st],i)){
for(int pst=0;pst<num;pst++){//上一行的状态
if(judge(ans[pst],i-1)&&!(ans[st]&ans[pst])){
dp[i][ans[st]]+=dp[i-1][ans[pst]];
}
}
}
}
}
int cnt=0;
for(int i=0;i<num;i++){
cnt=(cnt+dp[row][ans[i]])%mod;
}
cout<<cnt<<endl;
}
return 0;
}