C - Underwater Snipers UVALive - 5000 最小值最大化问题 二分
2017-04-01 17:58
309 查看
题目链接
题意:一条河岸线y=k,y>k区域有n个敌人,现在要在y<=k区域布置S个狙击手,狙击手的狙击范围为距离自己半径为D的圆内,问满足能够狙死所有的敌人的情况下,离河岸线最近的那个狙击手的离河岸线的最大距离是多少。
解法:求最小值最大的问题。二分这个距离,如果距离为x,那么最好是狙击手都站到y=k-x处,可以最大范围地打到敌人。
然后check的时候求出每个敌人在y=k-x线上的能够打到他的狙击手范围,为[Xi-sqrt(D^2-(Yi-k+x)*(Yi-k+x),Xi+sqrt(D^2-(Yi-k+x)*(Yi-k+x)],
然后就变成了区间选点问题,将所有的范围按右端点排序,扫一遍判断这么多区间需要布置多少个狙击手,最后如果需要的>S,那么check失败,否则成功。
有一个需要注意的问题是,我以前做过类似的题目,贪心取点的题目...这个题和那个题有所不同,这个题对区间排序的时候我们需要直接根据区间右端点从小到大排序,不能按照左端点升序排序,如果相等在按照右端点升序排序,因为遇到区间套区间的那种情况会出错.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node
{
ll x1;
ll x2;
}q[maxn];
ll k,n,s,d;
ll x[maxn],y[maxn];
bool cmp(node a,node b)
{
return a.x2<b.x2;
}
int check(ll m)
{
for(int i=1;i<=n;i++)
{
if(d*d-(y[i]-k+m)*(y[i]-k+m)<0)
return 0;
q[i].x1=x[i]-(ll)sqrt(d*d-(y[i]-k+m)*(y[i]-k+m));
q[i].x2=x[i]+(ll)sqrt(d*d-(y[i]-k+m)*(y[i]-k+m));//坑啊...
}
sort(q+1,q+1+n,cmp);
ll ss=q[1].x2;
ll cou=1;
for(int i=2;i<=n;i++)
{
if(q[i].x1>ss)
{
cou++;
ss=q[i].x2;
}
}
if(cou>s)
return 0;
else
return 1;
}
int main()
{
int t;
int tt=1;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld %lld",&k,&n,&s,&d);
for(int i=1;i<=n;i++)
scanf("%lld %lld",&x[i],&y[i]);
ll l=0,r=d,mid,ans=-1;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid)==0)
{
r=mid-1;
}
else
{
l=mid+1;
ans=mid;
}
}
printf("Case %d: ",tt++);
if(r<0)
printf("IMPOSSIBLE\n");
else
printf("%lld\n",ans);
}
return 0;
}
题意:一条河岸线y=k,y>k区域有n个敌人,现在要在y<=k区域布置S个狙击手,狙击手的狙击范围为距离自己半径为D的圆内,问满足能够狙死所有的敌人的情况下,离河岸线最近的那个狙击手的离河岸线的最大距离是多少。
解法:求最小值最大的问题。二分这个距离,如果距离为x,那么最好是狙击手都站到y=k-x处,可以最大范围地打到敌人。
然后check的时候求出每个敌人在y=k-x线上的能够打到他的狙击手范围,为[Xi-sqrt(D^2-(Yi-k+x)*(Yi-k+x),Xi+sqrt(D^2-(Yi-k+x)*(Yi-k+x)],
然后就变成了区间选点问题,将所有的范围按右端点排序,扫一遍判断这么多区间需要布置多少个狙击手,最后如果需要的>S,那么check失败,否则成功。
有一个需要注意的问题是,我以前做过类似的题目,贪心取点的题目...这个题和那个题有所不同,这个题对区间排序的时候我们需要直接根据区间右端点从小到大排序,不能按照左端点升序排序,如果相等在按照右端点升序排序,因为遇到区间套区间的那种情况会出错.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node
{
ll x1;
ll x2;
}q[maxn];
ll k,n,s,d;
ll x[maxn],y[maxn];
bool cmp(node a,node b)
{
return a.x2<b.x2;
}
int check(ll m)
{
for(int i=1;i<=n;i++)
{
if(d*d-(y[i]-k+m)*(y[i]-k+m)<0)
return 0;
q[i].x1=x[i]-(ll)sqrt(d*d-(y[i]-k+m)*(y[i]-k+m));
q[i].x2=x[i]+(ll)sqrt(d*d-(y[i]-k+m)*(y[i]-k+m));//坑啊...
}
sort(q+1,q+1+n,cmp);
ll ss=q[1].x2;
ll cou=1;
for(int i=2;i<=n;i++)
{
if(q[i].x1>ss)
{
cou++;
ss=q[i].x2;
}
}
if(cou>s)
return 0;
else
return 1;
}
int main()
{
int t;
int tt=1;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld %lld",&k,&n,&s,&d);
for(int i=1;i<=n;i++)
scanf("%lld %lld",&x[i],&y[i]);
ll l=0,r=d,mid,ans=-1;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid)==0)
{
r=mid-1;
}
else
{
l=mid+1;
ans=mid;
}
}
printf("Case %d: ",tt++);
if(r<0)
printf("IMPOSSIBLE\n");
else
printf("%lld\n",ans);
}
return 0;
}
相关文章推荐
- UVALive 3971-Assemble- 最小值最大化(二分)
- UVALive 6198 A Terribly Grimm Problem 二分匹配 求字典序最小解
- UVALive 5000 Underwater Snipers --二分
- 【二分答案+贪心】解决“最小值最大”问题(UVa 12124 - Assemble)
- Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配
- poj 2456 Aggressive cows (最小值最大化二分问题)
- UVA Live 3211飞机调度问题-二分+2-SAT
- UVALive 5099 Nubulsa Expo 全局最小割问题
- Aggressive cows(最大化最小值问题(二分搜索))
- NWERC 2007 / UVa 12124 Assemble (二分搜索&最小值最大问题)
- QUTOJ 1359: 小菜的难题 最小值最大化问题 二分
- poj3258 二分 最小值最大化问题
- UVALIVE 5000 Underwater Snipers(二分+贪心)
- UVa live6492Welcome Party(二分最大匹配之最小点覆盖)
- NWERC 2007 / UVa 12124 Assemble (二分搜索&最小值最大问题)
- uvalive 3231 Fair Share 公平分配问题 二分+最大流 右边最多流量的结点流量尽量少。
- uvalive 3635 - Pie(二分搜索)
- uva 10020 Minimal coverage(贪心-最小覆盖问题)
- UVALive 2949 Elevator Stopping Plan(二分 + 贪心)
- uvalive 2326 - Moving Tables(区间覆盖问题)