CSU-2110: Keeping Cool

2110: Keeping Cool

Submit Page      Summary      Time Limit: 2 Sec       Memory Limit: 128 Mb       Submitted: 30       Solved: 4       SpecialJudge

Description

Kevin has just gotten back to his car after a morning at the beach and is about to drive away when he realises that he has left his ball somewhere. Thankfully, he remembers exactly where it is! Unfortunately for Kevin, it is extremely hot outside and any sand that is exposed to direct sunlight is very hot. Kevin’s pain tolerance allows him to only run for at most k seconds in the hot sand at one time. Kevin runs at exactly 1 metre per second on hot sand. Scattered around the beach are umbrellas. Each umbrella is a perfect circle and keeps the sand underneath it cool. Each time Kevin reaches an umbrella, he will wait there until his feet cool down enough to run for another k seconds on the hot sand. Note that Kevin will not run more than k seconds in the hot sand at one time, so if two umbrellas are more than k metres apart, Kevin will not run between them. Determine the minimum amount of time that Kevin must be in the sun in order to retrieve his ball and return back to the car.

Input

The first line of input contains four integers n (0 ≤ n ≤ 100), which is the number of umbrellas, k (1 ≤ k ≤ 100), which is the number of metres that Kevin can run on the hot sand, x (−100 ≤ x ≤ 100) and y (−100 ≤ y ≤ 100), which are the coordinates of the beach ball. Kevin starts at his car at (0; 0). You may treat Kevin and the ball as single points. The next n lines describe the umbrellas. Each of these lines contains three integers x (−100 ≤ x ≤ 100), y (−100 ≤ y ≤ 100) and r (1 ≤ r ≤ 100). The umbrella is a circle centred at (x; y) with radius r. There may be multiple items (ball, umbrella(s) or Kevin) at a single location. All measurements are in metres.

Output

Display the minimum amount of time (in seconds) that Kevin must be in the sun. If it is impossible for Kevin to get to the ball and return back to the car, display -1 instead. Your answer should have an absolute or relative error of less than 10−6.

Sample Input

0 1 0 0

0 20 1 2

0 10 20 20

2 2 7 4
6 2 2
2 2 1

1 2 3 3
0 3 2

Sample Output

0.0000000000

4.4721359550

-1

6.1289902045

4.0000000000

Hint

Source

South Pacific Divisionals

题意:某人一开始在车里,因为太阳很热,他至多只能在太阳下行走k米,当走到遮阳伞下时能恢复状态(行走距离变回k)问最多要在太阳下晒多少米,才能拿到他的球?二维坐标,每秒走一米

题解:首先很明显是一道图论题啊~我们以车为起点,对所有遮阳伞求最短到达时间(不违背行走规则)

当获得从起点到所有伞的最短时间时,再对车和所有伞求到达球所在位置的所有合法情况(注意因为球可能在伞的范围内,所以可以转化为到达某个伞的最短时间)

因为我们要从车到球再从球到车,相当于两个人从车到球,且两个人最后从到达球时在太阳底下晒的连续时间相加不超过k。故我们队上诉所有合法情况逐一判断(n^2,两个for)满足相加不超过k的就跟当前答案比较,取较小值!

综上,本题是一道水水的图论题。。。。

AC代码

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <stdio.h>

using namespace std;

const int maxn = 111;
const double inf = double(1 << 29);
double d[maxn];
const double eps = 1e-9;

struct node{
	double x, y, r;
}p[maxn];

double dis(double x1, double y1, double x2, double y2){
	return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

void di(int n, double k){
	d[0] = 0;
	queue<int> q;
	q.push(0);
	while(!q.empty()){
		int x = q.front();
		q.pop();
		for(int i = 1; i <= n; i++){
			if(x != i && dis(p[i].x, p[i].y, p[x].x, p[x].y) <= p[i].r + p[x].r + k){
				double d1 = max(0.0, dis(p[i].x, p[i].y, p[x].x, p[x].y) - p[i].r - p[x].r);
				if(d[i] > d[x] + d1){
					d[i] = d[x] + d1;
					q.push(i);
				}
			}
		}
	}
}

struct node1{
	double x1, t1;
	node1(double x, double t):x1(x), t1(t){}
};

vector<node1> qq;

bool cmp(node1 a1, node1 a2){
	return a1.t1 < a2.t1;
}

int main(){
	int n;
	double k, x, y;
	while(scanf("%d %lf %lf %lf", &n, &k, &x, &y) != EOF){
	    for(int i = 1; i <= n; i++)
	    	d[i] = inf;
		for(int i = 1; i <= n; i++)
			scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].r);
		p[0].x = 0;
		p[0].y = 0;
		p[0].r = 0;
		di(n, k);
		qq.clear();
		p[n + 1].x = x;
		p[n + 1].y = y;
		p[n + 1].r = 0;
		int loc = -1;
		for(int i = 0; i <= n; i++){
			if(dis(p[i].x, p[i].y, x, y) - p[i].r <= 0 && fabs(d[i] - inf) >= eps)
				loc = i;
		}
		if(loc == -1)
			loc = n + 1;
		for(int i = 0; i <= n; i++){
			if(dis(p[i].x, p[i].y, p[loc].x, p[loc].y) - p[i].r - p[loc].r <= k + eps){
				double tt = max(dis(p[i].x, p[i].y, p[loc].x, p[loc].y) - p[i].r - p[loc].r, 0.0);
				qq.push_back(node1(d[i] + tt, tt));
			}
		}
		int len = qq.size();
		double ans = inf;
		for(int i = 0; i < len; i++){
			for(int j = 0; j < len; j++){
				if(qq[i].t1 + qq[j].t1 <= k + eps)
				    ans = min(ans, qq[i].x1 + qq[j].x1);
			}
		}
		if(ans == inf)
            printf("-1\n");
        else
			printf("%.10lf\n", ans);
	}
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值