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 ;
}

 

你可能感兴趣的:(Advanced)