pku1727 Advanced Causal Measurements (ACM) .

 

 

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1727

题意简述:这题的题意还真有点难理解,给定一系列点,给定覆盖点数,要求求出覆盖点的最小t值最大。(覆盖规则题目已给出式子)

解题思路:二分+贪心。先对点按x升序排列,然后用二分枚举最大的最小t值,判断该枚举值是否可行,可行继续往上二分,否则往下二分。二分的初始上界:上界就是原给定点的最小t值,下界是一个很小的负数(由于题目中只给定了原始点的x范围,这里自己适当取值)。剩下的问题就是如何判断是否可行了:由题中给的公式t2 >= t1+|x2-x1|可以化简为:t1-t2+x2<=x1<=t2-t1+x2。有了这个式子就一直线扫过去,需要缩小范围就缩小范围,当该范围无解时,覆盖点数增加,重新设定范围。最终当覆盖点数如果大于题目给定的覆盖点数,则返回false;否则返回true。于是结果就出来了

 

#include<iostream>
#include<algorithm>
using namespace std;
const int Max=100002;
const int inf=1<<30;
int n,m;
struct P{
 int t,x;
}a[Max];
struct cmp
{
 bool operator ()(const P &a,const P &b) const
 {
  return a.x<b.x;
 }
};
bool check(int mid)
{
 int s=mid-a[1].t+a[1].x,e=a[1].t-mid+a[1].x;
 int num=1;
 for(int i=2;i<=n;i++)
 {
  if(mid-a[i].t+a[i].x>s)
   s=mid-a[i].t+a[i].x;
  if(a[i].t-mid+a[i].x<e)
   e=a[i].t-mid+a[i].x;
  if(s>e)
  {
   num++;
   s=mid-a[i].t+a[i].x;
   e=a[i].t-mid+a[i].x;
  }
 }
 if(num>m) return false;
 else return true;
}
int B_search(int start,int end)
{
    int Min=-inf;
    int s=start,e=end;
    while(s<=e)
    {
  int mid=(s+e)>>1;
  if(check(mid))
  {
   Min=mid;
   s=mid+1;
  }
  else e=mid-1;
    }
    return Min;
}
int main()
{
    int T;
    cin>>T;
    int Case=0;
    while(T--)
    {
  cin>>n>>m;
  int M=inf;
  for(int i=1;i<=n;i++)
  {
   cin>>a[i].t>>a[i].x;
   if(M>a[i].t) M=a[i].t;
  }
  sort(a+1,a+1+n,cmp());
  cout<<"Case "<<++Case<<": "<<B_search(-4000001,M)<<endl;
    }
    return 0;
}

你可能感兴趣的:(struct,search)