题意
有条宽为w的河流,两岸分别在x = 0, x = w处,河中间有n个石板。在河的一岸有一只青蛙想通过石板跳到对岸去。现在可以在河
中间某个位置多加一块石板,使得在单步跳跃中的最大值最小。
思路
Dijkstra变形,用两维来表示是否路径中使用过额外的石板。dis[0][u]表示没使用额外石板的最大最小,dis[1][u]表示使
用额外石板的最大最小。然后就用Dijkstra格式进行转移了。
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
#define lson rt << 1
#define rson rt << 1 | 1
#define bug cout << "BUG HERE\n"
#define ALL(v) (v).begin(), (v).end()
#define lowbit(x) ((x)&(-x))
#define Unique(x) sort(ALL(x)); (x).resize(unique(ALL(x)) - (x).begin())
#define BitOne(x) __builtin_popcount(x)
#define showtime printf("time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
#define Rep(i, l, r) for (int i = l;i <= r;++i)
#define Rrep(i, r, l) for (int i = r;i >= l;--i)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-8;
const double pi = 4 * atan(1);
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int nCase = 0;
const int maxn = 1e3 + 123;
struct point {
double x, y;
void read() {
scanf("%lf%lf", &x, &y);
}
double operator ^ (const point& rhs) {
return sqrt((x - rhs.x) * (x - rhs.x) + (y - rhs.y) * (y - rhs.y));
}
}a[maxn];
struct Edge {
int v, nxt;
double dis;
}e[maxn*maxn*4];
int head[maxn], ecnt;
void inline addedge(int u,int v,double dis) {
e[ecnt] = Edge{v, head[u], dis}, head[u] = ecnt++;
e[ecnt] = Edge{u, head[v], dis}, head[v] = ecnt++;
}
double dis[2][maxn];
int n, w;
struct node {
int u;
double md;
bool used;
point o;
bool operator < (const node& rhs) const {
return md > rhs.md || (md == rhs.md && used > rhs.used);
}
};
void gao() {
point ans;
double m = INF;
priority_queue<node> que;
Rep(i, 0, n + 1) dis[0][i] = dis[1][i] = INF;
que.push(node{
0, 0, false, point{
0, 0}});
dis[0][0] = 0;
while(!que.empty()) {
node temp = que.top();
que.pop();
int u = temp.u;
if (u == n + 1) {
printf("%.12lf %.12lf\n", temp.o.x, temp.o.y);
return ;
continue;
}
for (int i = head[u]; ~i;i = e[i].nxt) {
int v = e[i].v;
if (v == 0) continue;
if (temp.used) {
if (dis[1][v] > max(temp.md, e[i].dis)) {
dis[1][v] = max(temp.md, e[i].dis);
que.push(node{v, dis[1][v], true, temp.o});
}
}else {
double x, y;
if (u != 0 && v != n + 1) {
x = (a[u].x + a[v].x) / 2.0;
y = (a[u].y + a[v].y) / 2.0;
}
if (u != 0 && v == n + 1) {
x = (a[u].x + w) / 2.0;
y = a[u].y;
}
if (u == 0 && v == n + 1) {
x = w / 2.0;
y = 0;
}
if (u == 0 && v != n + 1) {
x = a[v].x / 2.0;
y = a[v].y;
}
if (dis[0][v] > max(temp.md, e[i].dis)) {
dis[0][v] = max(temp.md, e[i].dis);
que.push(node{v, dis[0][v], false, point{
0, 0}});
}
if (dis[1][v] > max(temp.md, e[i].dis / 2.0)) {
dis[1][v] = max(temp.md, e[i].dis / 2.0);
que.push(node{v, dis[1][v], true, point{x, y}});
}
}
}
}
printf("%.12lf %.12lf\n", ans.x, ans.y);
}
int main(int argc, const char * argv[])
{
freopen("froggy.in","r",stdin);
freopen("froggy.out","w",stdout);
while(~scanf("%d%d", &w, &n)) {
Rep(i, 1, n) a[i].read();
memset(head, -1, sizeof head), ecnt = 0;
int vs = 0, vt = n + 1;
addedge(vs, vt, w);
Rep(i, 1, n) {
addedge(vs, i, a[i].x);
addedge(i, vt, w - a[i].x);
Rep(j, i + 1, n) {
addedge(i, j, a[i] ^ a[j]);
}
}
if (n == 0) {
printf("%.12lf 0\n", w / 2.0);
continue;
}
gao();
}
return 0;
}