POJ 1230 Pass-Muraille (贪心) 解题报告

博客讲述了如何使用贪心算法解决POJ 1230问题,该问题涉及魔术师在有限魔力值下穿越墙的路径规划。作者强调了贪心算法的最优子结构和贪心可行性,并分享了从错误中学习的经验,提醒注意题目细节,如墙端点的顺序不确定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

       有一个舞台,可以看做网格状的区域,平行于X轴的方向上有n面墙,所有的墙的厚度都是一个单位,但是长度不同,没有一个网格会在多面墙中。魔术师要表演穿墙魔术,他的魔力值有限,只能穿越k面墙。现在观众任意挑选一列(平行于Y轴),魔术师在这一列上,平行于Y轴从最上面穿到最下面。现在给出魔力值k和n面墙的信息,求最少拆几面墙可以让魔术师可以沿任意观众选择的列穿过所有的墙。

思路:

  一开始想用贪心的做,但是思维比较浮,直接去想在某一列中,如何让左边和右边都尽可能远,于是思路又跳到搜索上……其实贪心有两个性质:最优子结构和贪心可行性,我没有考虑子结构这个性质。如果把思维沉下来,从左到右扫描,如果这一列没问题就pass,如果有问题就拆能往右延伸的尽可能远的墙。

对,就是酱紫,我们总是动不动就把一个题想的很难,其实,把思维跳回来,多从基础的角度分析,仔细分析,往往有更多的眼界。

还学到的:

  这道题一开始WA了,但怎么都找不出错,看了Discuss中一组数据才发现,题目中只说给定一面墙的两个端点(x,y),但没有说一定先给左端点,后给右端点!!!也就是右端点可能在左端点前面给出!!!论思维定势的严重性……

最后,贴代码:

#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 105;
int lx[MAXN],ly[MAXN],rx[MAXN],ry[MAXN];
int wall[MAXN];
bool exist[MAXN];
int main()
{
	int T,cas;
	int n,k,i,j,p;
	int max_x;
	scanf("%d",&T);
	for (cas = 1; cas <= T; ++cas)
	{
		memset(wall,0,sizeof(wall));
		max_x = 0;
		scanf("%d %d",&n,&k);
		for (i = 0; i < n; ++i)
		{
			scanf("%d %d %d %d",&lx[i],&ly[i],&rx[i],&ry[i]);
			if (rx[i] < lx[i])
			{
				int tmp = lx[i];
				lx[i] = rx[i];
				rx[i] = tmp;
			}
			if (rx[i] > max_x)
				max_x = rx[i];
			for (j = lx[i]; j <= rx[i]; ++j)
				++wall[j];
			exist[i] = true;
		}
		int ans = 0;
		for (i = 0; i <= max_x; ++i)
		{
			if (wall[i] <= k)
				continue;
			int chai = wall[i] - k;
			for (j = 0; j < chai; ++j)
			{
				int cnt = -1;
				for (p = 0; p < n; ++p)
				{
					if (lx[p] <= i && rx[p] >= i && (cnt == -1 || rx[p] > rx[cnt]) && exist[p] == true)
						cnt = p;
				}
				exist[cnt] = false;
				for (p = lx[cnt]; p <= rx[cnt]; ++p)
					--wall[p];
			}
			ans += chai;
		}
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值