POJ初级分类 贪心专题 poj1328 POJ2109 POJ 2586

题目1328

代码及解释:

/*

POJ1328
Radar Installation
题目大意:有一条海岸线,一边是海岸,一边是大海;海中有一些小岛,我们要建造一些雷达,从而可以覆盖所有小岛,要求雷达的最小数目。
思路:贪心法的套路。每次计算对小岛做一个半径为d的圆,如果与x轴有交点的话(如果有任何无交点的情况,输出-1),那么就用勾股定理计算出来算出来每个岛与x轴交点
的两个坐标,分别是    left    和    right   ,如果A岛得到的left在B岛的right左面,那么A岛与B岛肯定可以共圆,so不需要建筑一个雷达,反之,继续建造。
只想说,贪心好强,但是不好想啊。。。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

struct Point
{
    int x;
    int y;
}p[1005];
struct position
{
    double left;
    double right;
}pos[1005],temp;

bool cmp(position a,position b)
{
    return a.right<b.right;
}
int n,d;
//用勾股定理计算出每个圆与x轴交点的左右横坐标
void Cx()
{
    for(int i=0;i<n;i++)
    {
        double s = sqrt(1.0*d*d-1.0*p[i].y*p[i].y);
        pos[i].left = (double)p[i].x - s;
        pos[i].right = (double)p[i].x + s;
    }
}
int main()
{
    int t=0;
    while(~scanf("%d%d",&n,&d)&&(n||d))
    {
        int flag=0;//判断是否有不能覆盖的情况
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            if(p[i].y>d)
                flag=1;
        }
        printf("Case %d: ",++t);
        if(flag)//-1的情况
        {
            cout<<-1<<endl;
            continue;
        }
        Cx();
        sort(pos,pos+n,cmp);

        int sum=1;
        temp=pos[0];
        for(int i=1;i<n;i++)
        {
            if(pos[i].left>temp.right)//如果A岛得到的left不在B岛的right左面
            {
                sum++;
                temp=pos[i];
            }
            else if(pos[i].right<temp.right)//圆被包含
                temp=pos[i];
        }
        printf("%d\n",sum);
    }
    return 0;
}

题目:POJ2109

/*float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;
double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308。*/

所谓的贪心竟然是卡double精度,有的人想到log()就错了,因为log(k,p)是不能直接计算的,所以要化为log(p)/log(k),然后就是多次运算带来的误差不能承受了。

(看了下知乎,了解了范围带来的影响,没有范围这种bug方法不能过的)主要是1<=k<=109,精度限制就没问题了。

当然,“正规”方法是高精度。

代码及解释:

/*float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;
double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308。*/
#include <iostream>
#include<cstdio>
#include<cmath>
using namespace std;

int main()
{
    double n,p;
    while(~scanf("%lf%lf",&n,&p))
    {
        cout<<pow(p,1.0/n)<<endl;
    }
    return 0;
}


高精度



题目链接

理解题意一直都是硬伤,英语进步缓慢啊,好好反思一下,是自己太烂太贪玩了啊

题目大意及AC代码:

/*
poj2586
Y2K Accounting Bug
题目大意(好难懂):这个公司出事了,进病毒了,每个月可能盈利可能亏损,但是公司竟然不记得了,公司(((每个连续的五个月)))报表一次,一共就八次喽,
1~5,2~6……
只记得每次报表都亏了,所以,让计算这个公司还有可能盈利吗,如果可能,最多能盈利多少
思路:在保证每个五个月都亏损,但是亏损尽量少,就可以求得最大收益了。
这就要求任意连续的五个月中至少有一个是亏损的,并且尽量使亏损减少
情况不多,就是枚举啦,然后根据s和d的范围确定最后的盈利与否
1.  ssss d ssss d ss    10个盈利月数,2个亏损月数,任意五个月1个亏损月
2.  sss dd sss dd ss    8个盈利月数,8个亏损月数,任意五个月2个亏损月
3.  ss ddd ss ddd ss    6个盈利月数,6个亏损月数,任意五个月3个亏损月
4.  s dddd s dddd sd    3个盈利月数,9个亏损月数,任意五个月4个亏损月
5.  dddddddddddd        0个盈利月数,12个亏损月数,任意五个月0个亏损月
*/


#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int s,d;
    int ss,dd;
    while(~scanf("%d%d",&s,&d))
    {
        if(d>4*s)
        {
            ss=10;
            dd=2;
        }
        else if(2*d>3*s)
        {
            ss=8;
            dd=4;
        }
        else if(3*d>2*s)
        {
            ss=6;
            dd=6;
        }
        else if(4*d>s)
        {
            ss=3;
            dd=9;
        }
        else
        {
            ss=0;
            dd=12;
        }
        if(ss*s-dd*d>=0)
            printf("%d\n",ss*s-dd*d);
        else
            printf("Deficit\n");
    }
    return 0;
}

贪心的方法应该类似吧,感觉这也是一种贪心的思想

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值