poj1230 Pass-Muraille

题意 : 有一块棋盘式的场地和一个魔术师,场地中有n道墙,魔术师一次最多能穿越k道墙。求移除最少数量的墙,使得魔术师可以在场地的任意一列表演都可以成功。

/*
本题使用贪心:
1.使用一个结构体Wall进行存储
2.对所有的墙进行排列(按墙的左端点进行排列)
3.每次对同一列上的墙进行扫描,若无法穿墙,就寻找出对后续的墙影响最大的那一堵,也就是右端点最大的一堵
*/
#include<iostream>
#include<algorithm>
using namespace std;
struct Point
{
	double x,y;
};
struct Wall
{
	Point left,right;//墙的左端点以及右端点
}w[105];
bool cmp(Wall w1,Wall w2)
{
	if(w1.left.x==w2.left.x) return w1.right.x<w2.right.x;
	else return w1.left.x<w2.left.x;
}
int search(int n,int k) //贪心
{
	if(k==0) return n;
	int t1,t,i;
	int flag[105]={0}; //墙的标记,若已移去,则为1
	for(i=k;i<n;i++)
	{
		t=i;
		t1=1;
		int count=0;
		while(t--)   //对之前所有墙进行扫描
		{
			if(t1>i) break;
			else if(w[i].left.x>w[i-t1].right.x && flag[i-t1]==0)
			{
				t1++;
			}
			else if(w[i].left.x<=w[i-t1].right.x)     //两墙在同一列
			{
				if(flag[i-t1])   //若墙已经移去,则继续向前扫描
				{
					while(flag[i-t1])
					{
						t1++;
					}
					t++;
				}
				else
				{
					t1++;
					count++;
				}
			}
			
		}
		if(count>=k) //判断是否满足同一列上是否有k堵墙
		{
			int no=i;
			double max=w[i].right.x;
			t=i;
			t1=1;
			while(t--)
			{
				if(t1>=i) break;
				else if(w[i-t1].right.x>max)
				{
					if(flag[i-t1])
					{
						while(flag[i-t1])
						{
							t1++;
						}
						t++;
					}
					else
					{
						max=w[i-t1].right.x;
						no=i-t1;
						t1++;
					}
				}
				else t1++;
			}
			flag[no]=1;  
		}
	}
	int ans=0;
	for(i=0;i<n;i++)
	{
		if(flag[i]) ans++;  
	}
	return ans;
}
int main()
{
	int t,n,k,i,x;
	while(scanf("%d",&t)!=EOF)
	{
		for(x=0;x<t;x++)
		{
			scanf("%d%d",&n,&k);
			for(i=0;i<n;i++)
			{
				scanf("%lf %lf %lf %lf",&w[i].left.x,&w[i].left.y,&w[i].right.x,&w[i].right.y);
				if(w[i].left.x>w[i].right.x)  //易忽略的地方
				{
					double temp=w[i].left.x;
					w[i].left.x=w[i].right.x;
					w[i].right.x=temp;
				}
			}
			sort(w,w+n,cmp);
			printf("%d\n",search(n,k));
		}
	}
	return 0;
}


 
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值