1. 程式人生 > >poj 2663 Tri Tiling (狀壓dp+多米諾骨牌問題+滾動陣列反思)

poj 2663 Tri Tiling (狀壓dp+多米諾骨牌問題+滾動陣列反思)

本來直接一波狀壓dpAC的

#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;

typedef long long ll;
ll dp[50][10];
int path[15][2], p, n, m = 3;

void dfs(int l, int now, int pre)
{
	if(l > m) return;
	if(l == m)
	{
		path[p][0] = pre;
		path[p++][1] = now;
		return;
	}
	
	dfs(l + 1, (now << 1) | 1, pre << 1);
	dfs(l + 1, now << 1, (pre << 1) | 1);
	dfs(l + 2, (now << 2) | 3, (pre << 2) | 3);
}

int main()
{
	dfs(0, 0, 0);
	while(~scanf("%d", &n) && n != -1)
	{
		memset(dp, 0, sizeof(dp));
		dp[0][(1 << m) - 1] = 1;
		_for(i, 1, n) 
			REP(j, 0, p)
				dp[i][path[j][1]] += dp[i-1][path[j][0]];	
		printf("%lld\n", dp[n][(1 << m) - 1]);
	}
	return 0;
}

然後閒著無聊想用滾動陣列優化一下,雖然說對於這道題完全沒必要

然後就發現了問題

每次使用的時候要清空這一行的值

因為這道題的狀態轉移是+=, 以前都是=,所以值可以直接覆蓋。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;

typedef long long ll;
ll dp[2][10];
int path[15][2], p, n, m = 3;

void dfs(int l, int now, int pre)
{
	if(l > m) return;
	if(l == m)
	{
		path[p][0] = pre;
		path[p++][1] = now;
		return;
	}
	
	dfs(l + 1, (now << 1) | 1, pre << 1);
	dfs(l + 1, now << 1, (pre << 1) | 1);
	dfs(l + 2, (now << 2) | 3, (pre << 2) | 3);
}

int main()
{
	dfs(0, 0, 0);
	while(~scanf("%d", &n) && n != -1)
	{
		memset(dp, 0, sizeof(dp));
		int t = 0;
		dp[t][(1 << m) - 1] = 1; t ^= 1;
		_for(i, 1, n) 
		{
			REP(j, 0, p) dp[t][path[j][1]] = 0; //這一行是關鍵 
			REP(j, 0, p)
				dp[t][path[j][1]] += dp[t^1][path[j][0]];	
			t ^= 1;
		}
		printf("%lld\n", dp[t^1][(1 << m) - 1]);
	}
	return 0;
}