D 导弹发射
Description
Alpha 机构研发出一种新型智能导弹,它能够在雷达检测到的区域内,选择一条前进的路径,击破路径上所有的目标物。雷达位于(0,0)处,它能够检测到两条射线之间的区域(不妨设在第一象限)。导弹一开始置放在(0,0)处,它可以在雷达能检测到的区域内先选择一个目标物击破,然后再继续前进,选择另一个目标物击破。注意,导弹不能沿着这两条射线前进,当然也不能停在原地。可以假设,导弹一旦发射,其能量无比大,前进的路径无限长。已知雷达能够检测到区域,其射线 1:ax-by=0 和射线 2:cx-dy=0。Alpha 机构的总指挥希望在发现目标群的第一时刻,计算出一条可以击破最多目标物的路径。Input
第一行: T 表示以下有 T 组测试数据(1≤T ≤8)对每组测试数据:第 1 行: n 表示目标物的个数第 2 行: a b c d 代表两条射线的斜率分别是 a/b 和 c/d。接下来有 n 行,每行 2 个正整数 xi yi 即第 i 个目标物的坐标。(1) n<=10^5 0<=a, b, c, d<=10^5 a 和 b 不会同时为 0,c 和 d 不会同时为 0;(2) 0<= xi , yi <=10^6 i=1,…..,nOutput
每组测试数据,输出占一行,即导弹能击破的最多目标数。
Sample Input
1151 3 2 13 16 24 22 54 56 63 41 62 17 49 35 31 315 512 4Sample Output
4解题思路: 首先,我们只需要考虑在曲线之内的点。然后思考,如何判断导弹是前进的?(这个问题在比赛的时候一直困扰我)我们将两条射线看成x轴和y轴进行坐标变换,有了新的坐标后,很容易可以判断前进的情况(x递增,y递增)。变换之后用nlogn的LIS求解即可。这里要注意一个问题,当x轴不变,y轴增大时,LIS有可能将其统计在内。我们在排序时设置,当x相等时y从大到小排序,可以解决上述问题。
这题的题面其实表达的不是很清楚,比如是否有多个目标在同一位置,两条射线的相对位置是否固定。。。然而题目在不考虑这些因素的情况下都能A。。。
代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N=110000;
struct node
{
double x,y;
}a[N],b[N];
bool cmp(node a,node b)//先按x从小到大排序,如果x相等按y从大到小排序,这样排除了沿y轴前进的情况
{
if(a.x==b.x) return a.y>b.y;
return a.x<b.x;
}
int Search(int num,int low,int high)
{
int mid;
while(low<=high)
{
mid=(low+high)/2;
if(a[num].y>b[mid].y) low=mid+1;
else high=mid-1;
}
return low;
}
int dp(int n)//LIS nlogn模板
{
int i,len,pos;
b[1].x=a[1].x;
b[1].y=a[1].y;
len=1;
for(int i=2;i<=n;i++)
{
//两个点在同一位置的情况,数据中没有
//if(a[i].y>b[len].y&&a[i].x>b[len].x||a[i].x==b[len].x&&a[i].y==b[len].y)
if(a[i].y>b[len].y&&a[i].x>b[len].x)
{
len=len+1;
b[len].y=a[i].y;
b[len].x=a[i].x;
}
else
{
pos=Search(i,1,len);
b[pos].y=a[i].y;
b[pos].x=a[i].x;
}
}
return len;
}
int main()
{
int T,n;
double a1,b1,c1,d1;
cin>>T;
while(T--)
{
cin>>n;
cin>>a1>>b1>>c1>>d1;
//保证c1/d1射线在a1/b1上面,数据中不存在相反情况
/*if(b1==0||c1==0||(b1!=0&&d1!=0&&c1/d1<a1/b1))
{
swap(a1,c1);
swap(b1,d1);
}*/
int cnt=0;
for(int i=1;i<=n;i++)
{
double x,y;
scanf("%lf%lf",&x,&y);
//如果点在两个射线之内
if(y*d1<x*c1&&x*a1<y*b1)
{
cnt++;
//坐标变换
a[cnt].x=(x-y*d1/c1)*c1/sqrt(c1*c1+d1*d1);
a[cnt].y=(y-x*a1/b1)*b1/sqrt(a1*a1+b1*b1);
}
}
sort(a+1,a+cnt+1,cmp);
cout<<dp(cnt)<<endl;
}
}