洛谷P1003 铺地毯

原题链接
思路:
这题是在模拟的关卡里,我网上找了半天对模拟还不是很理解,我觉得说的好点的就是这个:

在自然界和日常生活中,许多现象具有不确定的性质,有些问题甚至很难建立数学模型,
或者很难用计算机建立递推、递归、枚举、回溯法等算法。在这种情况下,一般采用模拟
策略。所谓模拟策略就是模拟某个过程,通过改变数学模型的各种参数,进而观察变更这
些参数所引起的过程状态的变化,由此展开算法设计。

这题按照题目所给的输入,先输入n,然后我是将每组(a,b,g,k)存入结构体数组中,然后输入x,y。将结构数组从下标n-1遍历满足(x, y)就输出序号,否则输出-1.

struct Data {
	int x;
	int y;
	int a;
	int b;
};

int main() {
	int n;
	sfd(n);
	Data* data = new Data[n];
	for( int i=0; i<n; i++ ) {
		sfd(data[i].x);
		sfd(data[i].y);
		sfd(data[i].a);
		sfd(data[i].b);
	}
	int x, y, i;
	sfd(x);
	sfd(y);
	for( i=n-1; i>=0; i-- ) {
		if( x>=data[i].x&&x<=(data[i].x+data[i].a)&&y>=data[i].y&&y<=(data[i].y+data[i].b) ) {
			pfd(i+1);//i+1就是地毯编号
			break;
		}
	}	
	if( i<0 ) {
		pfd(-1);
	}
	return 0;
}
<think>嗯,用户问的是洛谷的P1228题目,用C语言解决。首先,我需要确定这道题的具体内容。洛谷的题目编号P1228可能对应不同的题目,但根据常见的题目列表,P1228通常是“地毯填补问题”或者类似的递归分治题目。比如,用L型地毯覆盖缺口的棋盘问题。假设是这个题目,我需要回忆题目要求。 题目大意是,在一个2^k × 2^k的棋盘上,有一个方格被挖去,需要用L型的地毯覆盖其余所有方格,且不能重叠。用户需要用C语言编写程序,输出每个地毯的位置和方向。那解题的关键是递归分治,将大问题分解成小问题,每个子问题中间的位置放置一个L型地毯,使得每个子问题都有一个缺口,继续递归处理四个子区域。 接下来,用户可能需要步骤解释。首先,确定递归基,当k=1时,直接铺剩下的三个方块。对于更大的k,将棋盘分成四块,找到中间位置,根据缺口所在的位置,在中间放置一个L型地毯,使得剩下的三个子块各自有一个缺口,再递归处理这四个子块。 然后,考虑如何确定每个地毯的位置和方向。例如,如果缺口在左上角的子区域,那么在中间位置放置一个右下方向的L型地毯,这样其他三个子区域的中间位置就各有一个缺口。递归处理这四个子区域。 接下来是C语言实现的关键点。需要处理递归函数,参数包括当前棋盘的大小、缺口的位置、当前处理的区域坐标。递归函数每次将棋盘分成四个部分,计算中间点的位置,并根据缺口的位置放置地毯,然后递归调用四个子区域。 可能的代码结构大致如下:主函数读取k和缺口坐标,调用递归函数。递归函数处理每个子棋盘,直到大小为1时处理基本情况。每次递归中间放置地毯,并处理四个子区域。 需要注意的是,缺口的位置需要正确传递到每个子区域。例如,如果原缺口在左上子区域,则中间放置的L型地毯会在其他三个子区域生成新的缺口,递归处理时需要传递这些新的缺口位置。 可能遇到的难点是正确计算各个子区域的坐标和缺口的位置。例如,每个子区域的边长是当前边长的1/2,所以需要计算中间点,并确定各个子区域的起始坐标。 此外,输出格式需要正确,每个地毯由三个坐标组成,表示覆盖的三个方块的中心位置。例如,中间放置的L型地毯的三个块的位置需要根据方向来确定坐标。 测试样例可能帮助验证。例如,当k=2,缺口在(1,1)时,输出应包含多个地毯的位置,确保覆盖所有方格除了缺口。 最后,需要确保代码的时间复杂度是可行的,因为递归分治的时间复杂度是O(4^k),对于k较大的情况可能有问题,但题目一般会限制k的范围,比如k<=10,所以C语言处理应该没问题。 总结步骤:理解分治策略,确定递归函数,处理坐标和缺口位置,正确输出每个地毯的位置。需要注意边界条件和递归终止条件。</think>洛谷题目 P1228 通常为“地毯填补问题”,属于递归与分治的经典题目。以下是使用C语言的解题思路与实现步骤: --- ### **题目概述** 在 $2^k \times 2^k$ 的棋盘上,某1个方格被挖空。用L型地毯(覆盖3个方格)铺满剩余区域,要求地毯不重叠且覆盖所有非空方格。输出每个地毯的位置。 --- ### **核心思路:递归分治** 1. **问题分解** 将棋盘分为4个 $2^{k-1} \times 2^{k-1}$ 的子棋盘。其中一个子棋盘包含缺口,其余三个需在中间交汇处放置一个L型地毯,为每个子棋盘“制造”一个缺口。 2. **递归基** 当 $k=1$ 时,直接铺放一个L型地毯覆盖剩余3个方格。 3. **中间处理** 在每层递归中,根据缺口位置,确定中间L型地毯的方向,并递归处理4个子棋盘。 --- ### **C语言代码实现** ```c #include <stdio.h> #include <math.h> // 递归函数:(x,y)为当前棋盘左上角坐标,hole为缺口位置,size为当前棋盘边长 void cover(int x, int y, int hx, int hy, int size) { if (size == 1) return; int half = size / 2; // 中间点坐标 int mid_x = x + half - 1; int mid_y = y + half - 1; // 判断缺口在哪个子棋盘 if (hx <= x + half - 1 && hy <= y + half - 1) { // 缺口在左上子棋盘 printf("%d %d 1\n", mid_x + 1, mid_y + 1); cover(x, y, hx, hy, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else if (hx <= x + half - 1) { // 缺口在右上子棋盘 printf("%d %d 2\n", mid_x + 1, mid_y); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, hx, hy, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else if (hy <= y + half - 1) { // 缺口在左下子棋盘 printf("%d %d 3\n", mid_x, mid_y + 1); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, hx, hy, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else { // 缺口在右下子棋盘 printf("%d %d 4\n", mid_x, mid_y); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, hx, hy, half); // 右下 } } int main() { int k, x, y; scanf("%d %d %d", &k, &x, &y); int size = pow(2, k); cover(1, 1, x, y, size); return 0; } ``` --- ### **代码解析** 1. **递归函数 `cover`** - 参数 `(x, y)` 表示当前棋盘的左上角坐标,`(hx, hy)` 是缺口位置,`size` 是当前棋盘边长。 - **关键步骤**:计算中间点,判断缺口所在子棋盘,输出L型地毯位置,递归处理四个子区域。 2. **输出格式** - 每行输出格式为 `a b c`,表示地毯覆盖的三个方格中心坐标为 `(a,b)`,方向由 `c` 决定(1-4对应四种方向)。 --- ### **样例输入与输出** **输入:** ``` 2 1 1 ``` **输出:** ``` 2 2 1 1 1 4 1 2 3 2 1 2 ``` --- ### **注意事项** 1. **坐标转换**:题目中棋盘的坐标通常从1开始,需注意边界计算。 2. **时间复杂度**:递归深度为 $k$,每层处理4个子问题,总时间复杂度为 $O(4^k)$,适用于 $k \leq 10$。 3. **验证正确性**:可通过小规模测试(如k=1,2)手动验证覆盖逻辑是否正确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值