POJ 1727 Advanced Causal Measurements (ACM) (二分+贪心)

这个题开始没读懂,很久才明白,题目是要寻找在所有点之下(两条直线的下面)的m个点中最小的t值的最大值,然后又想了很久,没想出好办法,看到discuss是二分,才想到二分答案,开始对每个点进行排序,对每个点做斜率为-1的线,与y轴相较,按照交点的大小进行从小到大的顺序排序,原因就是当二分答案时,利用贪心的思想对这些点遍历,很容易就可以计算出最少需要多少个因事件,(很多谈心题目也都是利用这一点来贪心的),二分过后,输出最大的t值就可以了。

#include <iostream>
#include
<cstdio>
#include
<memory.h>
#include
<algorithm>
using namespace std;

#define MAXN 100050
#define INF (1<<30)
#define CLR(x,y) (memset(x,y,sizoef(x)))
int gi,gj,n,gn,r_val,m;
struct Node{
int x,y;
int val;
}node[MAXN];
bool cmp(const Node& a,const Node& b)
{
return a.val<b.val;
}
inline
bool _is(const int& val)
{
gn
= 1;
r_val
= node[0].x + node[0].y - val;
for(gi = 1; gi < n; ++gi)
{
if(node[gi].x-node[gi].y+val > r_val)
{
r_val
= node[gi].x + node[gi].y - val;
++gn;
}
if(gn > m )
return false;
}
return true;
}
int main()
{
int b_mid,b_low,b_high,ans,tt;
int i,j,tmp,mmin,ttt;
scanf(
"%d",&tt);
ttt
= 0;
while(tt--)
{
++ttt;
b_low
= -2000050;
scanf(
"%d %d",&n,&m);
mmin
= INF;
for(i = 0; i < n; ++i)
{
scanf(
"%d%d",&node[i].y,&node[i].x);
node[i].val
= node[i].x+node[i].y;
mmin
= mmin<node[i].y?mmin:node[i].y;
}
b_high
= mmin;
sort(node,node
+n,cmp);
while(b_low <= b_high)
{
b_mid
= (b_low+b_high)>>1;
if(_is(b_mid))
{
ans
= b_mid;
b_low
= b_mid+1;
}
else
b_high
= b_mid-1;
}
printf(
"Case %d: %d\n",ttt,ans);
}
return 0;
}

原文地址:https://www.cnblogs.com/lvpengms/p/1690005.html