NYACM_006

NYACM_006

题目:喷水装置(一)
链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=6
描述:

描述
现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会

让以它为中心的半径为实数Ri (0 < Ri<15)的圆被湿润,这有充足的喷水装置i(1< i<600)个,并且一定能把草坪全部湿润,你要做的是:选择尽量少的喷水装置,把整个草坪的全部湿润。

输入
第一行m表示有m组测试数据
每一组测试数据的第一行有一个整数数n,n表示共有n个喷水装置,随后的一行,有n个实数ri,ri表示该喷水装置能覆盖的圆的半径。
输出
输出所用装置的个数
样例输入
2
5
2 3.2 4 4.5 6
10
1 2 3 1 2 1.2 3 1.1 1 2
样例输出
2
5

分析:

想要喷水装置最少,采用贪心算法,总是选择当前可用最大的,覆盖尽可能多的范围。不过贪心算法存在缺点,即不是最优解,先试试看能不能AC。
只是试一试而已,居然直接AC了,考虑到未必能够充分利用到所能用到的最大面积,比如剩余若干个小块虽然总面积小于下一个最大块覆盖面积,但是由于分布不同位置,一块可能不够,类似华容道那样,不过难度只有3,可能没有这种特殊的测试数据,当然也可能是自己想多了。

AC Code
/*
贪心算法求解NYACM_006
*/


#include <vector>  //使用vector存储,直接利用sort排序,方便从大到小选择使用
#include <algorithm>
#include <iostream>
#include <cmath>

using namespace std;

double GetLeftArea(double LeftArea, double size)
{
    double ret;
    double area;
    if (fabs(size - 2) <= 1e-9)
    {
        area= 2 * size*size;
    }
    else
    {
        area= sqrt(size*size - 1) * 4;
    }   
    //cout << "use " << size << " area is " << area << endl;
    ret= LeftArea - area;
    if (ret < 0)
    {
        ret = 0;
    }
    return ret;
}

int main()
{
    int m;  //M组测试数据    
    cin >> m;
    while (m--)
    {
        int n;  //n个装置
        cin >> n;
        vector<double> Devices;
        int counter=0;
        for (int i = 0; i < n; i++)
        {
            double tmp;  //喷水范围实数
            cin >> tmp;
            Devices.push_back(tmp);
        }
        sort(Devices.begin(), Devices.end());

        //草坪长20,宽2,喷水范围Ri [0,15],整个草坪湿润相当于覆盖整个草坪
        //每个喷水装置覆盖的面积范围:
        //如果Ri<=1,即整个圆都在草坪内,但是要求覆盖全部,取最大面积内接正方形 2*Ri*Ri
        //如果Ri>1,即有在草坪外部分,圆心在中轴线上能覆盖最大面积,此时最大面积为 sqrt(Ri*Ri-1)*2*2
        //覆盖整个面积2*20
        //实际摆放应该更复杂,要考虑形状等,暂且这样编程,看能否通过
        double leftArea = 40;
        for (int i = Devices.size() - 1; i >= 0; i--)
        {
            counter++;
            //cout << "now use " << Devices[i] << endl;
            leftArea = GetLeftArea(leftArea, Devices[i]);
            //cout << "now leftArea is " << leftArea << endl;
            if (fabs(leftArea) < 1e-9 )
            {
                break;
            }
        }           
        cout << counter << endl;

    }
}
其他:

提交后会自动跳转到运行结果,上面AC code时间/内存是4/312,看到下面有0/236的,可能采用了更高效的做法吧,不过从头过一遍各个题的目的是扩展视野,以后不太可能参加ACM比赛了,暂且这样吧,以后再尝试降低时间/内存。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值