ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Gym100851F Froggy Ford 最短路变形

2020-03-28 20:53:27  阅读:296  来源: 互联网

标签:diss dist max 石头 Gym100851F second Froggy Ford first


网址:https://codeforces.com/gym/100851

题意:

在一段宽度为$w$的河上有$n$个石头,石头的位置确定,用坐标$(x,y)$表示,河左岸的方程是$x=0$,右岸的方程是$x=w$,有一只青蛙将从左岸沿着这些石头跳到右岸(不借助石头也可以),现在打算在这条河上再加一个石头,求出新的石头的位置,使得在加上这个石头后,青蛙通过这条河时路径上的跳跃的最大长度最小。

题解:

这个题也是套路题了,河的左岸和右岸一定是当成一点起点和一个终点。然后我们预处理出起点和终点到每个石头上的路径的边权最大值,用$dijkstra$求即可,转移方程是$dis[v]=max(dis[u],cur_edge)$。求的时候需要重新建图,因为不能从一个石头跳到起点\终点,再跳到另一个石头上。建完图之后我们求出了$diss和dist$。然后我们就求$min(max(diss[u],e(u->v),dist[v]))$,找到这个$u,v$。

有$4$种情况:

$u=$起点,$v!=$终点,则这个石头的坐标是$(\frac{x_v}{2},y)$。

$v=$终点,$u!=$起点,则这个石头的坐标是$(\frac{w+x_u}{2},y)$。

$u=$起点,$v=$终点,则这个石头的坐标是$(\frac{w}{2},0)$。

其他,则这个石头的坐标是$(\frac{x_u+x_v}{2},\frac{y_u+y_v}{2})$。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
typedef long long ll;
pair<double, double>p[N];
int n;
double w;
struct edge
{
	int to;
	double w;
	bool operator <(const edge& a)const
	{
		return w > a.w;
	}
};
vector<edge>G[N];
double len(pair<double, double>& a, pair<double, double>& b)
{
	return sqrt((a.first - b.first) * (a.first - b.first) +
		(a.second - b.second) * (a.second - b.second));
}
double dist[N], diss[N];
bool vis[N];
void dijkstra(int s, double* dis)
{
	priority_queue<edge>q;
	for (int i = 0; i <= n + 1; ++i)
		dis[i] = 0x3f3f3f3f3f3f3f3f;
	memset(vis, 0, sizeof(vis));
	q.push({ s,0 });
	dis[s] = 0;
	while (q.size())
	{
		edge cur = q.top();
		q.pop();
		if (vis[cur.to])
			continue;
		vis[cur.to] = 1;
		for (auto i : G[cur.to])
			if (max(dis[cur.to], i.w) < dis[i.to])
			{
				dis[i.to] = max(dis[cur.to], i.w);
				q.push({ i.to,dis[i.to] });
			}
	}
}
void init1()
{
	for (int i = 0; i <= n + 1; ++i)
		G[i].clear();
	for (int i = 1; i <= n; ++i)
	{
		G[0].push_back({ i,p[i].first });
		G[i].push_back({ n + 1,w - p[i].first });
	}
	for (int i = 1; i <= n; ++i)
		for (int j = i + 1; j <= n; ++j)
		{
			double d = len(p[i], p[j]);
			G[i].push_back({ j,d });
			G[j].push_back({ i,d });
		}
}
void init2()
{
	for (int i = 0; i <= n + 1; ++i)
		G[i].clear();
	for (int i = 1; i <= n; ++i)
	{
		G[n + 1].push_back({ i,w - p[i].first });
		G[i].push_back({ 0,p[i].first });
	}
	for (int i = 1; i <= n; ++i)
		for (int j = i + 1; j <= n; ++j)
		{
			double d = len(p[i], p[j]);
			G[i].push_back({ j,d });
			G[j].push_back({ i,d });
		}
}
int main()
{
#ifndef _Aya
	freopen("froggy.in", "r", stdin);
	freopen("froggy.out", "w", stdout);
#endif
	scanf("%lf%d", &w, &n);
	for (int i = 1; i <= n; ++i)
		scanf("%lf%lf", &p[i].first, &p[i].second);
	init1();
	dijkstra(0, diss);
	init2();
	dijkstra(n + 1, dist);
	double maxn = 0x3f3f3f3f3f3f3f3f;
	double ansx = 0, ansy = 0;
	for (int i = 0; i <= n + 1; ++i)
		for (int j = 0; j <= n + 1; ++j)
		{
			double tmp;
			if (i == j)
				continue;
			if (i == 0 && j == n + 1)
				tmp = w;
			else if (i == 0)
				tmp = p[j].first;
			else if (j == n + 1)
				tmp = w - p[i].first;
			else
				tmp = len(p[i], p[j]);
			if (maxn > max(max(diss[i], tmp / 2), max(tmp / 2, dist[j])))
			{
				maxn = max(max(diss[i], tmp / 2), max(tmp / 2, dist[j]));
				if (i == 0 && j != n + 1)
					ansx = p[j].first / 2, ansy = p[j].second;
				else if (i != 0 && j == n + 1)
					ansx = (p[i].first + w) / 2, ansy = p[i].second;
				else if (i == 0 && j == n + 1)
					ansx = w / 2, ansy = 0;
				else
					ansx = (p[i].first + p[j].first) / 2, ansy = (p[i].second + p[j].second) / 2;
			}
		}
	printf("%lf %lf\n", ansx, ansy);
	return 0;
}
/*
10 7
2 2
2 4
5 1
5 3
8 2
7 5
9 4
*/

 

标签:diss,dist,max,石头,Gym100851F,second,Froggy,Ford,first
来源: https://www.cnblogs.com/Aya-Uchida/p/12589257.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有