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

Posted huatian5

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;


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

以上是关于POJ初级分类 贪心专题 poj1328 POJ2109 POJ 2586的主要内容,如果未能解决你的问题,请参考以下文章

poj1328 贪心

贪心-poj1328

POJ 1328 Radar Installation(贪心)

poj 1328贪心

贪心poj1328:雷达设置

POJ 1328 Radar Installation 贪心算法