1. 程式人生 > >HihoCoder第九周 狀態壓縮 二 與POJ2411總結

HihoCoder第九周 狀態壓縮 二 與POJ2411總結

在此我向各位博友求助,特別想知道除了HihoCoder上面的結果要對1e9+7取餘之外,這兩道題還有什麼其他的問題,都是骨牌覆蓋問題,都是狀態壓縮+dp,為什麼我能過poj2411的程式過不了HihoCoder,還不是其他諸如TimeLimited,而是Wrong Answer,這個問題我想了很久,還是不知道是怎麼回事,如果有神通廣大的博友知道答案,希望你能告訴我。順便說一下,HihoCoder給的那個hint只看懂了一部分遞推的公式,其中滿足的那個條件還是不懂。

兩個題目的連線地址:

骨牌覆蓋問題我想了很久很久,我自己也知道對於每一個位置上的骨牌來說,有三種可能,有可能是上樓的骨牌,有可能是下樓的骨牌,也有可能是同樓層的骨牌。但當時我思考的時候,就在想,比方說2*2這個位置。


有兩種擺法,我當時就在想如何記錄result[1][1]=2,因為這兩種條件都滿足了,所以result[1][1]=2?那之後的result[1][2]呢?

覺得這樣不對。就完全沒有思路了。

最後看了一個動態規劃演算法,但其實這道題算動態規劃的話,我更覺得像列舉,列舉上樓的所有情況,列舉下樓的所有情況,看這兩種情況裡面,哪些合拍,之後才是動態規劃記錄其和的事。

首先覺得這種記錄方法很棒,即記錄兩層樓的狀態,如果是01代表豎著一個骨牌。如果是10代表,樓上的骨牌怎麼來的不知道,但從樓下豎著一塊牌是確定的。如果是11,說明都是橫著的牌,所以樓上和樓下的下一張牌都要是1才能滿足條件。如果是00,則GG。

之後就是第一層的初始化,只需記住1要成對出現就行了(因為這是第一層)。

被這題折磨太久,印象實在太深。希望交流。

#include <iostream>
#include <cstring>
using namespace std;

#define M 12

long long dp[12][1<<M];
int n,m;

int init_ok(int i)
{
	int count;
	for(count=m-1;count>=0;)
	{
		if((i>>count)&1)
		{
			if((i>>(count-1))&1)
			{
				count= count-2;
				continue;
			}
			else
			{
				count--;
				return 0;
			}
		}
		else
		{
			if(count==1&&(i&1))
				return 0;
			else
			{
				count--;
				continue;
			}
		}

	}
	return 1;
}

void init()
{
	int count;
	int kongjian = (1<<m)-1;

	memset(dp,0,sizeof(dp));

	for(count=0;count<=kongjian;count++)
	{
		if(init_ok(count))
			dp[0][count]=1;
	}
}

bool match(int a, int b)
{
	for (int i = 1; i < 1 << m;)
	{
		if (((a & i) == 0) && ((b & i) == 0))
			return false;
		if ((a & i) && (b & i))
		{
			if ((a & (i << 1)) && ((b & (i << 1))))
			{
				i <<= 2;
				continue;
			}
			else
				return false;
		}
		i <<= 1;
	}
	return true;
}

int main()
{

	while(scanf_s("%d %d",&n,&m),n &&m)
	{
		int i,shang,xia;
		if(n < m)
			i = n ,n = m,m =i;
		int kongjian = (1<<m)-1;

		init();

		for(i=1;i<n;i++)
		{
			for(xia = 0;xia<=kongjian;xia++)
			{
				for(shang=0;shang<=kongjian;shang++)
				{
					if(match(shang,xia))
						dp[i][xia]+=dp[i-1][shang];

				}
			}
		}

		cout<<dp[n-1][kongjian]<<endl;
	}

	return 0;
}