hdu3832 Earth Hour

实际上此题是求最少用多少个点可以覆盖掉1、2、3这三个点,也就是一个覆盖的问题,求最少的灯数覆盖掉1、2、3,那么我们可以依照最短路径SPFA求法,首先建立模型,显然mapp[i][j]表示第i盏灯和第j盏灯是否相交或者相切,

是则赋值为1,否则为0,然后SPFA三次判断1、2、3是否连通,最后找出一个点到1、2、3三点距离最短就可以了 

#include <iostream>
#include <cmath>
using namespace std;
const int size = 300;
const int eps = 10000000;
struct circle
{     
      int x, y, r;
}a[size];
int dis(circle a, circle b)
{
    if (((a.x-b.x) * (a.x-b.x) + (a.y-b.y) * (a.y-b.y)) <= (a.r+b.r) * (a.r+b.r))return 1;
    return 0;   
}
bool inque[size];
int que[size];
int mapp[size][size];
int dist[5][size];
void SPFA(int s, int n, int kk)
{
     memset(inque, false, sizeof(inque));
     for (int i = 0; i <= n; i ++){
         dist[kk][i] = eps; 
     }     
     int rear, front;
     rear = 1, front = 0;
     que[front] = s;
     dist[kk][s] = 0;
     inque[s] = true;
     while (front< rear){
           int u = que[front ++];
           inque[u] = false;
           for (int i = 1; i <= n; i ++){
               if (dist[kk][i] > dist[kk][u] + mapp[u][i]){
                  dist[kk][i] = dist[kk][u] + mapp[u][i];
                  if (!inque[i]){
                     que[rear ++] = i;
                     inque[i] = true;
                  }             
               }    
           }      
     }
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t --){
          int n;
          scanf("%d", &n);
          for (int i = 1; i <= n; i ++){
              scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].r);
          }      
          for (int i = 1; i <= n; i ++){
              for (int j = 1; j<= n; j ++){
                  mapp[j][i] = mapp[i][j] = dis(a[i], a[j]);
              }    
          }
          for (int i = 0; i <= n; i ++){
              for (int j = 0; j <= n; j ++){
                  if (!mapp[i][j] && i!=j){
                     mapp[i][j] = eps;                  
                  }
              }    
          }     
          int check1 = false;
          SPFA(1, n, 1);
          if (dist[1][2] == eps || dist[1][3] == eps)check1 = true;
          SPFA(2, n, 2);
          if (dist[2][1] == eps || dist[2][3] == eps)check1 = true;
          SPFA(3, n, 3);
          if (dist[3][2] == eps || dist[3][1] == eps)check1 = true; 
          if (check1){ 
             printf("-1\n");
             continue;
          }
          int minn = INT_MAX;
          for (int i = 1; i <= n; i ++){
              if (minn > dist[1][i]+dist[2][i]+dist[3][i]){
                 minn = dist[1][i]+dist[2][i]+dist[3][i]; 
              }
          }
          printf("%d\n", n-1-minn);
    }
    return 0;    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值