UVa12227/LA4618 Wormholes

2024-06-19 19:52
文章标签 wormholes uva12227 la4618

本文主要是介绍UVa12227/LA4618 Wormholes,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

UVa12227/LA4618 Wormholes

  • 题目链接
  • 题意
  • 分析
  • 测试数据
  • AC 代码

题目链接

  本题是2009年icpc欧洲区域赛西北欧赛区的j题

  UVA - 12227 Wormholes

题意

  你有一艘星际飞船,飞船运行速度为1,打算从坐标a旅行到坐标b(出发时刻为0),已知n个虫洞(0≤n≤ 50)的信息:入口点坐标s,出口点坐标e,形成时间t,穿过虫洞后时间的迁移量d(−1000000≤t,d≤1000000)。所有坐标的x、y、z绝对值不超过10000,并且任意两点间的距离简化成欧式距离向上取整。求达到b点的最早时间。

分析

  由于穿过虫洞后时间的迁移量d可能为负数,一旦经过某虫洞存在负圈,那么即便首次到达虫洞入口的时间晚于其形成时间t,只要绕着此圈不停地来回,到达虫洞两端点的最早时间将回退到t和t+d。

  因此只要预处理虫洞,看每个虫洞是否能找出负圈,如果能找到负圈那么达到虫洞两端的最早时间为 t s = m i n ( S a s , t ) t_s=min(S_{as},t) ts=min(Sas,t) m i n ( t s + S s e , t + d ) min(t_s+S_{se},t+d) min(ts+Sse,t+d)。预处理之后,跑一边Bellman Ford就能得到答案。对每个虫洞预处理看能否找出负圈的过程类似Bellman Ford,不过实际上更高效,参见代码。

测试数据

  给一份测试数据

AC 代码

#include <iostream>
#include <queue>
using namespace std;#define N 110
int s[N][N], f[N], g[N], t[N], d[N], x[N], y[N], z[N], m, n; bool inq[N], cyc[N];int ceil_sqrt(int x) {int l = 0, r = min((x+1)>>1, 34642);while (l <= r) {int m = (l+r+1)>>1, y = m*m;if (y == x) return m;y < x ? l = m+1 : r = m-1;}return l;
}bool update(int i) {queue<int> q;for (int j=2; j<n; j+=2) {g[j] = (cyc[j] ? t[j] : max(t[i]+d[i]+s[i+1][j], t[j])) + d[j];if (g[j] + s[j+1][i] < t[i]) {f[i] = min(f[i], t[i]); f[i+1] = min(f[i+1], min(f[i]+s[i][i+1], t[i]+d[i]));return cyc[i] = true;}q.push(j); inq[j] = true;}while (!q.empty()) {int u = q.front(); q.pop(); inq[u] = false;for (int j=2; j<n; j+=2) if (!cyc[j]) {int v = max(g[u]+s[u+1][j], t[j]) + d[j];if (v < g[j]) {if (v + s[j+1][i] < t[i]) {f[i] = min(f[i], t[i]); f[i+1] = min(f[i+1], min(f[i]+s[i][i+1], t[i]+d[i]));return cyc[i] = true;}g[j] = v;if (!inq[j]) q.push(j), inq[j] = true;}}}return false;
}void solve() {cin >> x[0] >> y[0] >> z[0] >> x[1] >> y[1] >> z[1] >> m; n = 2;for (int i=0; i<m; ++i) cin >> x[n] >> y[n] >> z[n++] >> x[n] >> y[n] >> z[n++] >> t[n-2] >> d[n-2];for (int i=0; i<n; ++i) for (int j=i; j<n; ++j) s[i][j] = s[j][i] = ceil_sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]));for (int i=0; i<n; ++i) f[i] = s[i][0], cyc[i] = false;for (int i=2; i<n; i+=2) if (s[i][i+1] + d[i] < 0)f[i] = min(f[i], t[i]), f[i+1] = min(f[i+1], min(f[i]+s[i][i+1], t[i]+d[i])), cyc[i] = true;while (true) {bool updated = false;for (int i=0; i<n; i+=2) if (!cyc[i] && update(i)) updated = true;if (!updated) break;}queue<int> q;for (int i=2; i<n; ++i) q.push(i), inq[i] = true;while (!q.empty()) {int u = q.front(); q.pop(); inq[u] = false;for (int i=0, v; i<n; ++i) if ((v = s[i][u] + f[u]) < f[i]) {f[i] = v;if (!inq[i]) q.push(i), inq[i] = true;}if (u&1) continue;int w = u+1, v = max(f[u], t[u]) + d[u];if (v < f[w]) {f[w] = v;if (!inq[w]) q.push(w), inq[w] = true;}}for (int i=2; i<n; ++i) f[1] = min(f[1], f[i] + s[1][i]);cout << f[1] << endl;
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);int t; cin >> t;while (t--) solve();return 0;
}

这篇关于UVa12227/LA4618 Wormholes的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075995

相关文章

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

poj 3259 Wormholes 最短路

题目大意:虫洞问题,现在有n个点,m条边,代表现在可以走的通路,比如从a到b和从b到a需要花费c时间,现在在地上出现了w个虫洞,虫洞的意义就是你从a到b话费的时间是-c(时间倒流,并且虫洞是单向的),现在问你从某个点开始走,能回到从前 解题思路:其实给出了坐标,这个时候就可以构成一张图,然后将回到从前理解为是否会出现负权环,用bellman-ford就可以解出了

UVA558 - Wormholes(BellmanFord判负环)

UVA558 - Wormholes(BellmanFord判负环) UVA558 - Wormholes 题目大意:  有一个教授希望利用虫洞回到过去(还是从这个虫洞出来就到达了过去),给你虫洞形成的有向图,问教授能否回到过去。 解题思路:  利用BellmanFord判负环,如果不存在负环的话,那么最多经过N - 1次迭代就可以得到最短路,因为形成最短路最多N - 1个节点(起点不算

POJ3259 Wormholes 【Bellmanford判断是否存在负回路】

很简单的bellmanford题目,这里比较详细:http://blog.csdn.net/lyy289065406/article/details/6645790 直接代码 #include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <cstring>#include <cma

POJ - 3259 Wormholes(判断负环, Bellman Ford,SPFA)

虫洞能够时光倒流,判断能否在回到出发的位置的时候在出发的时候之前。(判断是否存在负环) 初学最短路,尝试着用了三种方法判断: 1、Bellman Ford (令d全部为0,仅用来判断负环)       OJ测试得157MS 2、Bellman Ford 结束后再来一轮松弛若松弛成功则存在负环。    235MS 3、Bellman Ford 用队列优化过的SPFA,判断是否存在一个点同队大

Wormholes POJ3259 (spfa)

题目:http://poj.org/problem?id=3259 题目大意:F组数据, 输入n, m, w,表示n块田地, m个田与田之间的关系,w个虫洞,从一块田到达另一块田需要花一定时间, 穿过虫洞时时间会倒流,问是否能够回到出发前的时间 解题思路:判断是否存在负环,若存在则一定能够回去。 #include<cstdio>#include<cstring>#include<algo

POJ 3259 *** Wormholes

题意:农场主有f个农场,每个农场有n个田地,m条路,w个虫洞,走路从田地s到田地e需要花费t1时间,而每个虫洞可以从田地q到田地p,且使得时间倒流t2。求对于每个农场,农场主是否能从田地i出发,回到田地i的时间是在他出发的时间之前? 想法:其实就是判断田地之间是否存在负循环,用bellmanford算法就可以了,但是还是WA了两次。因为我忽略了这m条路事实上是可以往返的。

I - Wormholes

题目: While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time t

poj 3259 Wormholes SPFA // Bellman-ford

//最水的模版题,记下来以后忘了可以看看。 //SPFA #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=0x3f3f3f3f; const int maxn=505; int n, m, w, d[maxn], inqueue[ma

【POJ No. 3259】虫洞 Wormholes

【POJ No. 3259】虫洞 Wormholes POJ题目地址 【题意】 在探索许多农场时,约翰发现了一些令人惊奇的虫洞。虫洞是非常奇特的,因为它是一条单向路径,可以将人穿越到虫洞之前的某个时间!约翰想从某个地点开始,穿过一些路径和虫洞,并在他出发前的一段时间返回起点,也许他将能够见到自己。 【输入输出】 输入: 第1行是单个整数F (1≤F ≤5),表示农场的数量。 每个