题意 : 有一块棋盘式的场地和一个魔术师,场地中有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;
}