NOI 4.5 动态规划 1665:完美覆盖

题目来源:http://noi.openjudge.cn/ch0405/1665/

1665:完美覆盖

总时间限制1000ms    内存限制65536kB

描述

一张普通的国际象棋棋盘,它被分成 8 8 (8 8 ) 64 个方格。设有形状一样的多米诺牌,每张牌恰好覆盖棋盘上相邻的两个方格,即一张多米诺牌是一张 1 2 列或者 2 1 列的牌。那么,是否能够把 32 张多米诺牌摆放到棋盘上,使得任何两张多米诺牌均不重叠,每张多米诺牌覆盖两个方格,并且棋盘上所有的方格都被覆盖住?我们把这样一种排列称为棋盘被多米诺牌完美覆盖。这是一个简单的排列问题,同学们能够很快构造出许多不同的完美覆盖。但是,计算不同的完美覆盖的总数就不是一件容易的事情了。不过,同学们发挥自己的聪明才智,还是有可能做到的。
现在我们通过计算机编程对 3 n 棋盘的不同的完美覆盖的总数进行计算。



任务
3 n 棋盘的不同的完美覆盖的总数进行计算。

输入

一次输入可能包含多行,每一行分别给出不同的 n ( 3 n 棋盘的列数 )。当输入 -1 的时候结束。

n
的值最大不超过 30.

输出

针对每一行的n 值,输出 3 n 棋盘的不同的完美覆盖的总数。

样例输入

2
8
18
-1

样例输出

3
153
2131

 -----------------------------------------------------

思路

动态规划。

f(2n) = a(2n) + a(2n-2)f(2) + a(2n-4)f(4) +… + a(4)f(2n-4) + a(2)f(2n-2)

其中

a(2) = 3, a(4) = a(6) = … = a(2n) = 2

多组输入,可以先把输入存着,按最大的输入计算,这时较小的那些输入的答案也一并计算出来了,可以避免重复计算

特别注意输入奇数的时候答案为0,以及输入0的时候答案为1为此WA了2次

-----------------------------------------------------

代码

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

long long dp[16] = {};					// 只有偶数有解,奇数直接无解(30->16)

int main()
{
	int n,mymax = 0,i,j;
	vector<int> in;
	while (cin >> n)
	{
		if (n==-1)
		{
			break;
		}
		if (n%2==0)
		{
			n /= 2;
		}
		else
		{
			n = -1;
		}
		in.push_back(n);
		mymax = max(mymax,n);
	}
	dp[0] = 1;
	dp[1] = 3;
	for (i=2; i<=mymax; i++)
	{
		dp[i] = 3*dp[i-1] + 2;
		if (i>2)
		{
			for (j=2; j<i; j++)
			{
				dp[i] += 2*dp[i-j];
			}
		}
	}
	vector<int>::iterator it;
	for (it=in.begin(); it!=in.end(); it++)
	{
		if (*it==-1)
		{
			cout << 0 << endl;
		}
		else
		{
			cout << dp[*it] << endl;
		}
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80950166
4.5