POJ 1328&&2109&&2586

  这次是贪心(水笔贪心)专题。

  先看1328,一道经典的导弹拦截(或者是打击?不懂背景)。

  大意是说在一个坐标系中有一些点(或是导弹),你要在x轴上建一些东西,它们可以拦截半径为d的圆范围中的点。问最少修建的个数,不可能输出-1。

  经典问题了哈,主要是把二维的转成一维。

  对于每个要拦截的点以d为半径画一个圆。会与x轴有0/1/2个交点。如果没有交点直接退出-1即可,一个交点也可以看成两个交点重合。

  这样我们就得到了一些线段,然后就是区间覆盖了。贪心走一遍即可。

  两个端点的坐标勾股定理就好了:x±sqrt(d^2-y^2)

  注意检查你的输出,我因为把Case 打成了case WA了N次(......)。

  CODE

#include<cstdio>
#include<math.h>
#include<algorithm>
using namespace std;
const int N=1005;
struct data
{
    double x,y;
}a[N];
int n,d,i,kinds,x,y;
inline void read(int &x)
{
    x=0; char ch=getchar(); int flag=1;
    while (ch<'0'||ch>'9') { if (ch=='-') flag=-1; ch=getchar(); }
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    x*=flag;
}
inline int comp(data a,data b)
{
    return a.x<b.x;
}
int main()
{
    for (kinds=1;;++kinds)
    {
        read(n); read(d);
        if (!n&&!d) break;
        bool flag=0;
        for (i=1;i<=n;++i)
        {
            read(x); read(y);
            if (y>d) flag=1;
            a[i].x=x-sqrt(1.0*d*d-1.0*y*y); a[i].y=x+sqrt(1.0*d*d-1.0*y*y);
        }
        if (flag) { printf("Case %d: -1\n",kinds); continue; }
        sort(a+1,a+n+1,comp);
        int ans=1; 
        double last=a[1].y;
        for (i=2;i<=n;++i)
        if (a[i].x>last) ++ans,last=a[i].y; else if (a[i].y<last) last=a[i].y;
        printf("Case %d: %d\n",kinds,ans);
    }
    return 0;
}

 

  2109:这是个智障题。

  有一个等式k^n=p,现在给出n,p,让你求出k

  这不是直接把p开n次方即可的事情吗?和贪心有何瓜葛?

  double的精度在这题应该不会炸,开方也不用手写或高精检验,在精度范围内(k在1~1e9之间),所以用pow来做分数次幂就行了。

  CODE

#include<cstdio>
#include<cmath>
using namespace std;
double n,p;
int main()
{
    while (scanf("%lf%lf",&n,&p)!=EOF) printf("%.0lf\n",pow(p,1/n));
    return 0;
}

 

  2586:一个很简单的贪心题。

  题目大意是一个二货公司每个月要么盈利s元,要么亏损d元,但是他们在一年中任意连续的5个月(1~5,2~6……)的盈亏和必须是负的。问你一年中可能盈利吗,可以就输出最大盈利值。

  想一下就知道亏损的月份放在最后面最好(可以被多次利用)

  所以假定他们12个月都盈利,在进行检查,如果和大于0就从后面开始修改。

  CODE

#include<cstdio>
#include<cstring>
using namespace std;
int sum,s,d,i;
bool f[15];
inline void check(int a,int b)
{
    for(;;)
    {
        int res=0;
        for (int i=a;i<=b;++i)
        if (f[i]) res+=s; else res-=d;
        if (res>=0)
        {
            int i=b;
            while (!f[i]&&i>a) --i;
            f[i]=0;
        } else break;
    }
}
int main()
{
    while (scanf("%d%d",&s,&d)!=EOF)
    {
        memset(f,true,sizeof(f));
        sum=0;
        for (i=1;i<=8;++i)
        check(i,i+4);
        for (i=1;i<=12;++i)
        if (f[i]) sum+=s; else sum-=d;
        if (sum<0) puts("Deficit"); else printf("%d\n",sum);
    }
    return 0;
}

 

posted @ 2018-02-12 16:09  空気力学の詩  阅读(160)  评论(0编辑  收藏  举报