题目:http://poj.org/problem?id=3254
1.枚举行;
2.把有影响的“放不放牛”加入参数中,用二进制数表示该位置放不放牛,再用十进制数表示二进制数;
3.优美的预处理list;
4.优美的位运算比较二进制。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,list[1435],cnt,a[15],d[15][4050],ans; const int INF=100000000; bool b[15]; /*计算有多少种合法者 :1431 int list[15][2]; void yu() { list[0][0]=1;list[0][1]=1; list[1][1]=1;list[1][0]=1; for(int i=2;i<=12;i++) { list[i][1]=list[i-2][1]+list[i-1][0]; list[i][0]=list[i-1][1]+list[i-1][0]; } printf("(%d)",list[12][1]+list[12][0]); } */ int qiu() { int s=0,r=1; for(int i=m;i;i--) { if(b[i])s+=r; r*=2; } return s; } void yu(int pre) { for(int i=pre+2;i<=m;i++) { b[i]=1; list[++cnt]=qiu(); yu(i); b[i]=0; } } int main() { scanf("%d%d",&n,&m); yu(-1); // for(int i=1;i<=cnt;i++) // printf("(%d) ",list[i]); memset(b,0,sizeof b); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) scanf("%d",&b[j]); int r=1; for(int j=m;j;j--) { if(b[j])a[i]+=r; r*=2; } } for(int i=0;i<=cnt;i++) if(!((~a[1])&list[i]))d[1][list[i]]++; for(int i=2;i<=n;i++) for(int j=0;j<=cnt;j++) { if((~a[i])&list[j])continue; for(int k=0;k<=cnt;k++) if((list[j]&list[k])==0) { // printf("j=%d k=%d ",list[j],list[k]); d[i][list[j]]=(d[i][list[j]]+d[i-1][list[k]])%INF; } } for(int i=0;i<=cnt;i++) ans=(ans+d[n][list[i]])%INF; printf("%d",ans); return 0; }