骨牌铺法--递归思路

题目描述
有1×n的一个长方形,用一个1×1、1×2和1×3的骨牌铺满方格。例如当n=3时为1×3的方格。此时用1×1、1×2和1×3的骨牌铺满方格,共有四种铺法。如图所示。

在这里插入图片描述

输入
输入n(n为自然数,并且1≤n≤30)

输出
输出骨牌铺法的方案数。

样例输入 Copy
3
样例输出 Copy
4

思路:设1*n时有F(n)种排法;

F(1)有1种;F(2)有2种;F(3)有4种;

n为4的时候,方法数F4的分析如下:

第一块放11,有一种方法;剩余3块方法数是F3=4种。根据乘法原理,该种情况的方法数是14=4。

第一块放12,有一种方法;剩余2块方法数是F2=2种。根据乘法原理,该种情况的方法数是12=2.

第一块放13,有一种方法;剩余1块方法数是F1=1种。该种情况方法数是11=1.

根据分类原理,F4=4+2+1=7种。

……

故n>=4的时候,Fn=Fn-1+Fn-2+Fn-3

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin >> n;
	int cnt[50]={0,1,2,4};
	for(int i=4;i<=n;i++){
		cnt[i]=cnt[i-1]+cnt[i-2]+cnt[i-3];
	}
	cout << cnt[n] << endl;
	return 0;
} 

#include<iostream>//慢 
#include<bits/stdc++.h>
using namespace std;
int bone(int n){
	if(n==1) return 1;
	if(n==2) return 2;
	if(n==3) return 4;
	else return bone(n-1)+bone(n-2)+bone(n-3);
}
int main(){
	int n;
	cin >> n;
	cout << bone(n) << endl;
	return 0;
}
<think>好的,用户想了解PTA平台上的棋盘覆盖问题,特别是使用分治的实现方,题目编号是6-6。首先,我需要回忆棋盘覆盖问题的基本概念。这个问题通常涉及在一个2^k×2^k的棋盘中,有一个特殊方格,需要用L型骨牌覆盖其他所有方格,每个骨牌覆盖三个方格,且不能重叠。 接下来,分治在这里的应用是关键。分治的步骤通常是分解、解决、合并。对于棋盘覆盖,分解棋盘时,需要将大棋盘分成四个较小的子棋盘,其中一个子棋盘包含特殊方格,而其他三个则没有。这时需要在中心位置放置一个L型骨牌,作为三个没有特殊方格子棋盘的公共特殊方格。这样每个子棋盘都变成了一个更小规模的棋盘覆盖问题,可以递归解决。 然后,用户提到PTA的6-6题,可能需要具体的代码实现。棋盘覆盖通常使用递归函数,参数包括当前棋盘的左上角坐标、特殊方格的位置和当前棋盘的大小。每次递归将棋盘分成四部分,处理每个子棋盘的情况,直到棋盘大小为1x1时结束。 需要注意的细节是,如何确定每个子棋盘的特殊方格位置,以及如何标记L型骨牌。通常使用一个全局的二维数组来表示棋盘,并用不同的数字标识不同的骨牌。每次递归调用时,根据特殊方格的位置,决定在中心放置骨牌的位置,并更新三个子棋盘的特殊方格。 可能的问题包括递归终止条件的处理,骨牌的正确标记,以及子棋盘划分时的坐标计算。例如,当棋盘分割为四个象限时,需要正确计算每个子棋盘的起始坐标和大小,并处理特殊方格所在的象限,对其他三个子棋盘在中心位置放置骨牌。 此外,用户提供的引用中提到分治的关键在于如何划分棋盘,确保每个子棋盘大小相同且包含一个特殊方格。这验证了上述方的正确性。同时,引用[2]关于n皇后问题的约束条件可能不直接相关,但说明用户对PTA上的算问题有广泛兴趣,可能需要更具体的棋盘覆盖解答。 最后,代码实现方面,需要使用递归函数,每次将棋盘分成四部分,处理每个部分,并正确填充骨牌编号。例如,使用变量tr、tc表示当前棋盘的左上角坐标,dr、dc表示特殊方格的位置,size是当前棋盘的大小。当size减半后,判断特殊方格所在的象限,并在中心位置放置骨牌,然后递归处理四个子棋盘。 总结思路后,需要将这些步骤转化为具体的代码,并确保符合PTA题目的输入输出要求,比如输出棋盘的覆盖情况,每个骨牌用不同的数字表示,特殊方格用特定符号标记。</think>### PTA棋盘覆盖问题分治实现思路 棋盘覆盖问题属于典型的分治算应用场景,其核心在于将$2^k×2^k$的棋盘划分为四个等大的子棋盘,通过递归处理子问题实现全局覆盖[^1]。 #### 分治步骤解析 1. **棋盘划分**:每次将棋盘平均分为四个象限(子棋盘) 2. **特殊方格定位**:判断原始特殊方格所在的象限 3. **中心骨牌放置**:在三个不包含特殊方格的子棋盘交汇处放置L型骨牌 4. **递归处理**:将新生成的三个特殊方格作为子问题递归处理 #### 算实现关键点 ```python def chess_cover(board, tr, tc, dr, dc, size, tile): global tile_num if size == 1: return t = tile_num tile_num += 1 s = size // 2 # 判断特殊方格位置 if dr < tr + s and dc < tc + s: # 在左上象限 chess_cover(board, tr, tc, dr, dc, s, t) else: board[tr + s - 1][tc + s - 1] = t chess_cover(board, tr, tc, tr+s-1, tc+s-1, s, t) # 处理其他三个象限... ``` #### 具体实现说明 1. **数据结构**:使用二维数组表示棋盘,初始特殊方格标记为-1 2. **递归参数**: - `tr,tc`:当前棋盘左上角坐标 - `dr,dc`:特殊方格坐标 - `size`:当前棋盘尺寸 3. **覆盖过程**: - 每次递归将尺寸减半 - 在中心位置放置L型骨牌(除特殊方格子棋盘外) - 递归处理四个子棋盘 #### 复杂度分析 $$T(n) = 4T(n/4) + O(1)$$ 根据主定理可得时间复杂度为$O(n^{\log_3 4})$,空间复杂度$O(\log n)$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值