sincerit Tiling_easy version(动态规划)

Tiling_easy version
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10340 Accepted Submission(s): 7870

Problem Description
有一个大小是 2 x n 的网格,现在需要用2种规格的骨牌铺满,骨牌规格分别是 2 x 1 和 2 x 2,请计算一共有多少种铺设的方法。

Input
输入的第一行包含一个正整数T(T<=20),表示一共有 T组数据,接着是T行数据,每行包含一个正整数N(N<=30),表示网格的大小是2行N列。

Output
输出一共有多少种铺设的方法,每组数据的输出占一行。

Sample Input
3
2
8
12

Sample Output
3
171
2731

题目分析;第n个位置有两种方法装满,一种是通过n-2的装满情况通过1*2的砖平着叠放,或者一个22的块直接放置,也可以通过n-1然后用12竖着放
为什么不考虑两个竖着放的呢?
因为铺第i个位置的时候用一个竖的,必定是第i-1个位置铺好了,用不上两块竖着放
用两个横着放的是在第i-2的位置上考虑的
用两块竖着的可以用两次一块竖着的替代

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
ll dp[40]; // dp[i]表示铺到第i个位子时的种类数
// 转移方程 对于铺第i个位置 
//dp[i] = 2*dp[i-2](一个田字+两块横着放就是两个dp[i-2]相加) + dp[i-1](块竖的);
// 这里不要考虑用两块竖的  因为铺第i个位置的时候用一个竖的必定是
// 第i-1个位置铺好了
// 初始条件 dp[0] = 1; 
int main() {
  int m, n;
  scanf("%d", &m);
  while (m--) {
    scanf("%d", &n);
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for (int i = 1; i <= n; i++) {
      if (i == 1) dp[i] = 1;
      else dp[i] = 2 * dp[i-2] + dp[i-1];
    }
    printf("%lld\n", dp[n]);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/sincerit/article/details/84622511