poj 1230 Pass-Muraille

poj  1230  Pass-Muraille                      题目链接:http://poj.org/problem?id=1230

贪心水

题目大意:魔术师要表演穿墙魔术,舞台上有墙,魔术师有k单位的能量,也就是说他能穿过k面墙,但舞台上的墙可能会有多于k面的情况,问最少要拆几面墙,使得魔术师能表演成功?

题目分析:舞台是一个二维数组,墙都是横的,魔术师表演时则是按列走,所以我想可以用一个一维数组存下当前每一列的状态(有多少层墙),然后通过遍历一维数组来判断这一列是拆还是不拆。如果需要拆,就要选择拆哪一面(拆墙一拆拆一面,而不是拆一格,一开始没理解好),分析可得,拆对后面影响最大的墙是最优方案,也就是要拆从此点到右边距离最远的一面(或几面墙)。代码中拆墙动作循环边界为j<status[i]-k+j,最后还要加个j,原因是每拆一面墙,status[i]当前位置就要减1,边界变了,要使它不变,就要加上j。

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	int wl,wr,wtr;//wall left,wall right,wall to right
}wall[150];
int cmp(node a,node b)
{
	return a.wtr>b.wtr?1:0;
}
int main()
{
	int t,n,k,nothing,status[150],max_r,ans;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		ans=max_r=0;
		memset(status,0,sizeof(status));
		for(int i=0;i<n;i++)
		{
			scanf("%d%d%d%d",&wall[i].wl,¬hing,&wall[i].wr,¬hing);
			if(wall[i].wl>wall[i].wr)//坑啊,一开始没注意到这个
			{
				nothing=wall[i].wl;
				wall[i].wl=wall[i].wr;
				wall[i].wr=nothing;
			}
			if(wall[i].wr>max_r)max_r=wall[i].wr;
			for(int j=wall[i].wl;j<=wall[i].wr;j++)
			{
				status[j]++;
			}
		}
		for(int i=0;i<=max_r;i++)
		{
			//	printf("status[%d]-%d=%d\n",status[i],k,status[i]-k);
			if(status[i]>k)
			{
				for(int j=0;j<n;j++)//找对后面影响最远的 
				{
					if(wall[j].wl>i)wall[j].wtr=0;//把当前列无墙的赋0 
					else wall[j].wtr=wall[j].wr-i;
				}
				sort(wall,wall+n,cmp);
				for(int j=0;j<status[i]-k+j;j++)//拆墙的动作在这里 改了 !!!!!!!
				{
					//printf("走了一遍j=%d,status[i]-k=%d\n",j,status[i]-k);
					for(int jk=wall[j].wl;jk<=wall[j].wr;jk++)
					{
						status[jk]--;//具体拆,状态减 
					}
					for(int jk=0;jk<=max_r;jk++)
					{
					//	printf("%d",status[jk]);
					}
					//putchar('\n');
					wall[j].wl=wall[j].wr=wall[j].wtr=0;//拆完赋0 
					ans++;
				}
				//sort(wall,wall+n,cmp);
				//n-=status[i]-k;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}/*
1
8 2
0 0 0 0
0 1 0 1
5 0 5 0
5 1 5 1
1 1 4 1
0 2 2 2
3 2 5 2
4 3 1 3
*/
/*
1
5 2
1 0 1 0
1 0 1 0
1 9 1 9
1 9 1 9
1 2 1 2
*/
/*
1
4 2
1 0 1 0
1 3 1 3
1 9 1 9
1 2 1 2
*/
PS:实在不容易,一个小错折腾了一天多,code中带的测试数据后两个对我的错误有参考意义,很多网上的测试数据都对了,但还是WA,无语……

http://blog.sina.com.cn/s/blog_64018c250100wkju.html这篇blog很厉害的样子,最下面那个程序像是生成测试数据用的,不大懂……






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值