【poj2411】Mondriaan's Dream 狀壓dp

又是一道狀壓dp入門經典題!dp[i][j]表示第i行的狀態爲j時的狀態數。1表示放個豎着的。首先預處理判斷與0的個數,因爲只有偶數的時候才能放橫着的,轉移的時候只要與之前狀態邏輯與一下爲0並且邏輯或一下的狀態有偶數個0(邏輯與一下是因爲之前狀態豎着的)就是符合條件的,目標是dp[n][0]。

記得開long long

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll unsigned long long
using namespace std;
ll dp[15][1<<15];
int f[1<<15];
int n,m;
int main() {
	for (;(~scanf("%d%d",&n,&m))&&n;) {
		memset(f,0,sizeof(f));memset(dp,0,sizeof(dp));
		for (int i=0;i<1<<m;i++) {
			int cur=0;
			for (int j=0;j<m;j++) {
				if (i&(1<<j)) f[i]|=cur,cur=0;
				else cur^=1;
			}
			f[i]=(f[i]|cur)^1;
		}
		dp[0][0]=1;
		for (int i=1;i<=n;i++)
			for (int j=0;j<1<<m;j++) 
				for (int k=0;k<1<<m;k++)
					if ((j&k)==0&&f[j|k]) dp[i][k]+=dp[i-1][j];
		printf("%lld\n",dp[n][0]);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章