Hdu 4145 Cover The Enemy(大开脑洞)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4145

Cover The Enemy

Time Limit: 2000/1000 MS (Java/Others)    

Memory Limit: 65535/32768 K (Java/Others)



Problem Description
  Now, the war is coming, no one want to fight with others, but you have to when you are facing.
  As the king of a country, you should defend your country. The condition is that “There are N enemy armies around you, you have two towers and you want to build cannon on each tower to cover all the enemy armies”. The cannon has an “attack distance” R with a cost of R^2.
  You are facing a problem, to cover all the armies and make the cost R1^2 + R2^2 minimal, where R1 and R2 are the attack distance of the two towers.
 

Input
The first line contains an integer t, number of test cases, following with t groups of test cases described as following.
For each case, the first line contains four integers: x1, y1, x2, y2, the Coordinates of the two towers.
The next line is an integer n, the number of enemy armies, following with n lines of coordinates: x, y, which is the coordinate of a group of enemy army, where:
  t <= 100
1 <= n <= 100000, 
-1000 <= x, y <= 1000 
-1000 <= x1, y1, x2, y2 <= 1000
 

Output
The minimal cost of the two tower to cover all the enemy armies.
 

Sample Input
  
  
2 0 0 10 0 2 -3 3 10 0 0 0 6 0 5 -4 -2 -2 3 4 0 6 -2 9 1
 

Sample Output
  
  
18 30
 
题目大意:就是t组数据,然后又两个炮塔的坐标,n个敌人,你需要用这两个炮塔覆盖所有的敌人,花费的计算是用距离,比如其中一个炮塔覆盖的距离为r ,那么花费就是r^2,攻击范围就跟塔防一样是一个圆。
刚开始这题目就想到贪心,每次两个炮塔选择距离自己近的敌人,wa了几发,然后就看了几个大神的思路
就是把离塔1的距离排序,然后枚举,再用塔2来覆盖塔1覆盖不到的敌人
#include <bits/stdc++.h>
using namespace std;
struct N
{
    int len1,len2;      //与塔1的距离,与塔2的距离

}num[100010];
bool cmp(const N &a , const N &b)
{
    return a.len1 < b.len1;     //按距离1排序
}
int main()
{
    int t;
    scanf("%d",&t);
    int x1,x2,y1,y2;
    int n;
    while (t-- )
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        scanf("%d",&n);
        for (int i = 0 ; i < n ; i++ )
        {
            int a,b;
            scanf("%d%d",&a,&b);
            num[i].len1 = (a - x1 ) * (a - x1) + (b - y1) * (b - y1);       //分别计算距离
            num[i].len2 = (a - x2 ) * (a - x2) + (b - y2) * (b - y2);
        }
        sort(num,num+n,cmp);
        int ans = 0;
        int res = num[n-1].len1;       //在不需要用到塔2 所需要的花费
        for (int i = n - 2 ; i >= 0 ; i-- )
        {
            ans = max(ans , num[i+1].len2);         /*这个就是塔2到这个点的距离,因为排序是按离塔1的距离排的 所以用max来选择塔2的花费, 
                                                        举个例子, 假如塔1只覆盖到n-4这个点,那么就需要塔2来覆盖n-3,n-2,n-1这些敌人,那么只要用这些敌人中的最远距离就好了            */
            res = min(res , ans + num[i].len1);     //选择小的
        }
        ans = max(ans, num[0].len2);  
        res = min(res, ans); 
        printf("%d\n", res);  
    }
    return 0;
}



  
  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值