题意:
给出一个10矩阵 从中取有限个1 求没有上下左右没有相邻1的排列总数
解题思路:
1 先把每一排可以满足要求的排列情况枚举出来
2从题目给的每一行里面挑一种可以的情况 再从上一行挑一种可以的情况 要两行加起来也可以
3dp[i][state]=dp[i][state'] state'是所有满足state上一行的排列 总数全部加起来 最后得到答案
4注意位运算
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int p,q,sum,pq[20],can[1<<12],dp[20][1<<12];
int main()
{
int i,j,k,l,a;
while(~scanf("%d%d",&p,&q))
{
memset(pq,0,sizeof(pq));
memset(can,0,sizeof(can));
memset(dp,0,sizeof(dp));
for(i=0;i<p;i++)//把每一行读的数取反存在pq里 那么pq[i]=1的时候下一行的i位置才能取1 pq[i]=0时下一行只能取0
for(j=0;j<q;j++)
{
scanf("%d",&a);
if(!a) pq[i]+=(1<<(q-j-1));
}
for(i=0,j=0;i<(1<<q);i++)//用can存 在一行全部为1中挑选出 所有没有相邻1的排列情况
if((i&(i<<1))==0) can[j++]=i;//j最后的值就是一共有多少种排列数
for(i=0;i<j;i++)
if((pq[0]&can[i])==0) dp[0][i]=1;
//初始化dp[0] can[]其实是作为对照 后面符合的情况都是从这里挑出来再比较可不可以
for(i=1;i<p;i++)
for(k=0;k<j;k++)
if((pq[i]&can[k])==0)//以can做对照 挑一个可以的pq排列
for(l=0;l<j;l++)//再挑一个可以的can排列
if((pq[i-1]&can[l])==0&& (can[k]&can[l])==0)//这一排跟上一排不冲突就符合
dp[i][k]=(dp[i][k]+dp[i-1][l])%100000000;//题目要求输出mod100000000的值
for(i=0,sum=0;i<j;i++)
sum+=dp[p-1][i];
printf("%d\n",sum%100000000);
}
return 0;
}