POJ 1328题解

来源:互联网 发布:php 视频直播 编辑:程序博客网 时间:2024/06/07 09:51

题意简述

 

       题目给定岛屿个数(1<=n<=1000),雷达半径D(一开始认为是整数结果怎么都不对,其实D是小数)。。。。雷达只能在岸边,,一条直线上。。求覆盖所有岛屿需要最少的雷达数。。。如果无法覆盖,雷达数规定为-1。。。。。。。。。。其实就是岛屿坐标X,Y(Y>=0),,,雷达坐标X,0

 

算法分析

 

如果对岛屿进行各种算法的话一定很慢,因为岛屿是二维坐标。经过算法第指导可以考虑雷达本身在坐标上。于是想到了上图。画出来就是区间。重复最多的区间就可以覆盖最多的点。。画的不咋好,不过是这样 先把点安X轴排序 求出 每个岛屿对应雷达在X上的区间。。。从最左边的有区间开始 如果下一个点的左区间比现在的右区间还大 就要新的雷达。。如果下一个的右区间小于现在的右区间,需要將现在的右区间更新为小的,,因为必须覆盖所有点。。。。。。。。。最后一个点需要再建一个雷达。。
 
贪心算法:
它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解
 
不从整体最优上加以考虑对每一子问题求解,得到子问题的局部最优解。 每求出一个雷达就更接近最优解。。微笑
 
百度有个经典的例题
 

例题分析

[0-1背包问题]有一个背包,背包容量是M=150。有7个物品,物品不可以分割成任意大小。
要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
物品 A B C D E F G
重量 35 30 60 50 40 10 25
价值 10 40 30 50 35 40 30
分析:
目标函数:∑pi最大
约束条件是装入的物品总重量不超过背包容量:∑wi<=M(M=150)
⑴根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?
⑵每次挑选所占重量最小的物品装入是否能得到最优解?
⑶每次选取单位重量价值最大的物品,成为解本题的策略。
值得注意的是,贪心算法并不是完全不可以使用,贪心策略一旦经过证明成立后,它就是一种高效的算法。
贪心算法还是很常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。
可惜的是,它需要证明后才能真正运用到题目的算法中。
一般来说,贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。
对于例题中的3种贪心策略,都是无法成立(无法被证明)的,解释如下:
⑴贪心策略:选取价值最大者。
反例:
W=30
物品:A B C
重量:28 12 12
价值:30 20 20
根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。
⑵贪心策略:选取重量最小。它的反例与第一种策略的反例差不多。
⑶贪心策略:选取单位重量价值最大的物品。
反例:
W=30
物品:A B C
重量:28 20 10
价值:28 20 10
根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。
【注意:如果物品可以分割为任意大小,那么策略3可得最优解】
对于选取单位重量价值最大的物品这个策略,可以再加一条优化的规则:对于单位重量价值一样的,则优先选择重量小的!这样,上面的反例就解决了。
但是,如果题目是如下所示,这个策略就也不行了。
W=40
物品:A B C
重量:25 20 15
价值:25 20 15

POJ评定: 396K 0MS
 
代码

#include<stdio.h>#include<math.h>float a[1001],b[1001];void qsort(int s,int t){    int i,j;    float mid,tmp;    i=s; j=t; mid=a[i];    while (i <= j)    {        while (a[i] < mid)       i++;        while (a[j] > mid)      j--;        if (i <= j)        {   tmp=a[i];   a[i]=a[j];   a[j]=tmp;   tmp=b[i];   b[i]=b[j];   b[j]=tmp;            ++i;            --j;        }    }    if (s<j)      qsort(s,j);    if (i<t)      qsort(i,t); }int main(){    int n,i,x,y,d,leida,t=0;    float right,h;    scanf("%d %d",&n,&d);    while (n > 0 || d > 0)    {        ++t;  leida=0;        for (i=1;i <= n;++i)        {            scanf("%d %d",&x,&y);            if (y > d)    leida=-1;            h=sqrt((float)d*d-y*y);            a[i]=x-h;   b[i]=x+h;        }  if(leida == -1)  {      printf("Case %d: -1\n",t);   scanf("%d%d",&n,&d);   continue;  }        qsort(1,n);        right=b[1];  i=2;        while (i <= n)        {            if (a[i] > right)            {                ++leida;    right=b[i];            }            if (b[i] < right)                right=b[i];            ++i;        }        ++leida;        printf("Case %d: %d\n",t,leida);        scanf("%d %d",&n,&d);    }}


 

原创粉丝点击