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

来源:互联网 发布:淘宝vr资源怎么搜索 编辑:程序博客网 时间:2024/04/27 20:32

题目1328

代码及解释:

/*

POJ1328Radar 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代码:

/*poj2586Y2K 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 0