您的位置:首页 > 其它

pku1727 Advanced Causal Measurements (ACM)

2010-01-02 18:04 246 查看
题目链接: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<stdio.h>
#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;
scanf("%d",&T);
int Case=0;
while(T--)
{
scanf("%d%d",&n,&m);
int M=inf;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].t,&a[i].x);
if(M>a[i].t) M=a[i].t;
}
sort(a+1,a+1+n,cmp());
printf("Case %d: %d/n",++Case,B_search(-4000001,M));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: