POJ 1328 (贪心~又有点不一样)

题意:这道题目是讲给一个坐标轴,在x轴上方给n个点,表示岛屿坐标,然后给定雷达半径(雷达只能放在x轴上,雷达范围是一个圆),问最少需要多少雷达覆盖所有岛屿。

写这道题就觉得题很怪 我的方法也很怪  最后发现和大家写的方法不一样  所以就想记录下来。

首先,我们对所有的点排个序,先按x从小到大,在按y的绝对值从大到小。我们开始遍历每一个点,求出当前点的对于所有点的最优雷达(即表示我们把当前岛屿放在雷达边上,保证接下来最优),记录下此时的雷达坐标。然后继续遍历,判断当前岛屿是否在雷达范围内,如果不在(关键来了~~~)的话我们进行判断,岛屿是否在雷达的左边,如果是的话:我们把雷达向左移动(移动到当前岛屿正好在雷达边上)更新雷达坐标(不增加雷达数目),如果不是的话:我们再次建造一个新的雷达,更新雷达坐标。

即思想为 2步:

遍历排好序的每个岛屿  :

  如果岛屿在当前雷达范围外进行判断  岛屿是否在雷达左边,如果是执行1,如果不是执行2:

         1.把雷达向左移动,直到岛屿在雷达边上

         2.建造新的雷达,选取最优建造(即岛屿在雷达边上)

那么为什么呢?我仔细想了想,如果当前岛屿不在雷达范围内,且在雷达左边,那就只有在左上方喽,如果我们向左平移雷达坐标,那么之前在雷达当中的岛屿在平移后也还在雷达范围中,为什么?(圆嘛,他是圆的嘛,开玩笑,画个图看一下),如果在岛屿在雷达右边的话,就不行了,那就只能乖乖的在建造一个雷达了。这样我们就不会浪费任何一个雷达。总之大概是这样了。有什么漏洞的话欢迎大家提出~~  

第一次写,哈哈,请大家谅解!

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct ff{
    double x,y;
}f[1050];
bool cmp(ff a,ff b){
    return a.x==b.x?abs(a.y)>abs(b.y):a.x<b.x;
}
int main(){
    int n;
    double d;
    int cases=1;
    while(~scanf("%d%lf",&n,&d)){
        if(n==0&&d==0) break;
        double maxx=0,minn=0;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&f[i].x,&f[i].y);
            maxx=max(maxx,f[i].y);
            minn=min(minn,f[i].y);
        }
        printf("Case %d: ",cases++);
        if(abs(maxx)>d||abs(minn)>d){
            printf("-1\n");
            continue;
        }
        sort(f+1,f+1+n,cmp);
        double x=f[1].x+sqrt(d*d-f[1].y*f[1].y);
        int ans=1;
        for(int i=2;i<=n;i++){
            if(d<sqrt(f[i].y*f[i].y+abs(f[i].x-x)*abs(f[i].x-x))){
                if(f[i].x<x){
                    x=f[i].x+sqrt(d*d-f[i].y*f[i].y);
                }
                else{
                    x=f[i].x+sqrt(d*d-f[i].y*f[i].y);
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值