您的位置:首页 > 其它

HDU 5714 拍照(百度之星复赛)【宝宝的第一个爆0场】

2016-06-10 14:28 323 查看
【题目】

小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。

小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。

![http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg](http://acm.hdu.edu.cn/data/images/C715-1003-1.jpg)
 

[align=left]Input[/align]
第一行为T,表示输入数据组数。

下面T组数据,对于每组数据:

第一行是一个数n(1≤n≤104),表示船只的数量。

接下来n行,每行四个整数
x,y,z,d(−106≤x<y≤106,1≤z≤104),表示船只的左端点位置、右端点位置、距离河边的距离,以及航行的方向。d为−1表示向左航行,1表示向右航行。

 

[align=left]Output[/align]
对第i组数据,输出

Case #i:

然后输出一行,仅包含一个整数,表示最多可以拍到多少完整的船只。

 

[align=left]Sample Input[/align]

3
2
1 3 1 1
2 4 1 -1
2
1 3 1 -1
2 4 1 1
1
1 4 1 1

 

[align=left]Sample Output[/align]

Case #1:
2
Case #2:
1
Case #3:
0

【解题思路】对于船[x,y,z],当x+z>=y-z的时候,可以在[y-z,x+z]这些位置观测到它,那么我们可以处理出来n条线段,我们要求同一垂线交过的线段的数量最多,由于船是可以移动的,那么我们可以固定同一方向的船不动,假设初始在x位置观测往右的船,在y位置观测到往左的船,只要x<=y,那么经过一段时间我们就可以在同一角度观察到这些船。

那么如何求同一垂线交过的线段的数量最多,我们把线段的左端点的值当做1,右端点当成-1,然后就是一个累计的过程,我们要先预处理出每一个端点向左走的船的最大值,最后O(n)扫一遍即可。总复杂度nlogn。

【PS】啊啊啊啊啊啊,百度之星复赛爆0,没脸见人【掩面哭泣】其实就这个题就是个傻逼题啊。

【AC代码】

#include <bits/stdc++.h>
using namespace std;
const int maxn=20005;
int n;
struct node{
int x,val,d;//x代表端点值,val代表左端点还是右端点,d代表线段的方向
node(int x=0,int val=0,int d=0):x(x),val(val),d(d){}
bool operator<(const node &a)const
{
if(x!=a.x) return x<a.x;
if(val!=a.val) return val>a.val;
return d>a.d;
}
}boat[maxn];
int ans[maxn];//每一个端点向左走的船的最大值
int main()
{
int T,cas=1,x,y,z,d;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int cnt=0;
for(int i=0; i<n; i++)
{
scanf("%d%d%d%d",&x,&y,&z,&d);
int l=y-z,r=x+z;
if(l<=r)
{
boat[cnt++]=node(l,1,d);
boat[cnt++]=node(r,-1,d);
}
}
sort(boat,boat+cnt);
//预处理每一个端点向左走的船的最大值
memset(ans,0,sizeof(ans));
int now=0;
for(int i=cnt-1; i>=0; i--)
{
// if(boat[i].d<0)//向左走的船
// {
// if(boat[i].val==-1) now++;
// ans[i]=max(ans[i+1],now);
// if(boat[i].val==1) now--;
// //ans[i]=max(ans[i+1],now);
// }
if(boat[i].d<0&&boat[i].val==-1) now++;
ans[i]=max(now,ans[i+1]);
if(boat[i].d<0&&boat[i].val==1) now--;
ans[i]=max(now,ans[i+1]);
}
//for(int i=0; i<cnt; i++) cout<<ans[i]<<" ";cout<<endl;
//O(n)维护答案
now=0;
int maxans=0;
for(int i=0; i<cnt; i++)
{
if(boat[i].d>0)//向右走的船
{
if(boat[i].val==1) now++;
maxans=max(maxans,ans[i]+now);
if(boat[i].val==-1) now--;
maxans=max(maxans,ans[i]+now);
}
}
// printf("%d %d\n",cas++,maxans);
printf("Case #%d:\n",cas++);
printf("%d\n",maxans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: