@Acqua
2019-01-27T13:11:43.000000Z
字数 1085
阅读 978
动态规划
给定一个的棋盘,要在矩阵中放置棋子。每行有位置不能放,且上下左右不能相邻放置。求放置方案数。
预处理出行相邻情况、非法情况,打标记,然后再通过上一行限制推算该行方案数。表示第行状态为(预处理合法情况数组)的方案数,最终答案是(数组大小)。
// La Pluie Froid#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N=14;int lune[N],dp[N][1<<N],pluie[1<<N],n,m;int main(){scanf("%d %d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int x;scanf("%d",&x);lune[i]|=((!x)<<(j-1)); // 预处理非法放置}}int t=0;for(int i=0;i<(1<<m);i++){if(!(i&(i<<1))) pluie[++t]=i; // 如果行相邻,非法}for(int i=1;i<=t;i++){dp[1][i]=!(lune[1]&pluie[i]); // 如果第一行地形与第一行状态冲突,非法}for(int i=2;i<=n;i++){ // 枚举行for(int j=1;j<=t;j++){ // 枚举本行状态if(lune[i]&pluie[j]) continue; // 如果本行地形与本行状态冲突,非法for(int k=1;k<=t;k++){ // 枚举上一行状态if(lune[i-1]&pluie[k]) continue; // 如果上行地形与上行状态冲突,非法if(pluie[j]&pluie[k]) continue; // 如果本行状态与上行状态冲突,非法dp[i][j]+=dp[i-1][k];}}}int ans=0;for(int i=1;i<=t;i++){ans=(ans+dp[n][i])%100000000;}printf("%d",ans);return 0;}