题意:给一个图,1是可以放,0是不能放,可以放的地方放的不能相邻,求所有情况
题解:状压dp
参考博客:http://www.tuicool.com/articles/JVzMVj
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<iomanip> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define pi acos(-1) #define ll long long #define mod 100000000 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define MIN(a,b) a<b ? a:b using namespace std; const double g=10.0,eps=1e-9; const int N=15,maxn=30,inf=1<<29; int n,m,top; int cur[N],state[1<<N]; int dp[N][1<<N];//dp[i][j]是前i行,每行有前j种排列方式 bool ok(int x)//判断x中是否有1相邻的状态 { if(x & x<<1)return 0; return 1; } void init() { top=0; for(int i=0;i< 1<<n;i++) if(ok(i)) state[++top]=i;//所有每行中的1不相邻的状态 } bool fit(int x,int k)//判断状态x与第k行状态是否重合 { if(x & cur[k])return 0; return 1;//不重合就是1 } int main() { ios::sync_with_stdio(false); cin.tie(0); // cout<<setiosflags(ios::fixed)<<setprecision(3); while(cin>>m>>n){//m是行,n是列 init(); memset(dp,0,sizeof dp); for(int i=1;i<=m;i++) { cur[i]=0; int num; for(int j=1;j<=n;j++) { cin>>num; if(num==0)cur[i]+=(1 << (n-j));//cur记录每行的状态 } } for(int i=1;i<=top;i++) if(fit(state[i],1))//如果状态与第一行无重合 dp[1][i]=1; for(int i=2;i<=m;i++) { for(int k=1;k<=top;k++)//i行的所有状态 { if(!fit(state[k],i))continue; for(int j=1;j<=top;j++)//i-1行的所有状态 { if(!fit(state[j],i-1))continue; if(state[k]&state[j])continue;//上下有1相邻了 dp[i][k]=(dp[i][k]+dp[i-1][j])%mod; } } } int ans=0; for(int i=1;i<=top;i++) ans=(ans+dp[m][i])%mod; cout<<ans<<endl; } return 0; }