UVaLive 4128 Steam Roller (多决策最短路)
题意:给定一个图,r 根横线, c 根竖线。告诉你起点和终点,然后从起点走,每条边有权值,如果是0,就表示无法通行。走的规则是:如果你在下个路要转弯,会使这段路的时间加倍,但是如果一条路同时是这样,那么也只算两倍。起点和终点他们相连的第一条边也算两倍。问你最短时间。
析:把每个点拆成 8 个点(r, c, dir, doubled)分别下一步走哪个方向,是不是要加倍,然后每次枚举上一条,和新边,枚举上一边是不是加倍之后的,然后判断是不是要转弯,然后计算加不加倍,最后跑一次最短路,就好了。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(i,x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 80000 + 10;
const int maxm = 100 + 10;
const ULL mod = 10007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, -1, 0, 1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r >= 0 && r < n && c >= 0 && c < m;
}
const int UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3;
const int inv[] = {2, 3, 0, 1};
int id[maxm][maxm][4][2], cnt;
int g[maxm][maxm][4]; int ID(int r, int c, int dir, int doubled){
int &x = id[r][c][dir][doubled];
return x == 0 ? x = ++cnt : x;
} bool cango(int r, int c, int dir){
if(!is_in(r, c)) return false;
return g[r][c][dir] > 0;
} struct Edge{
int from, to, dist;
};
struct HeapNode{
int d, u;
bool operator < (const HeapNode &p) const{
return d > p.d;
}
}; struct Dijkstra{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
int d[maxn]; void init(int n){
this-> n = n;
for(int i = 0; i < n; ++i) G[i].cl;
edges.cl;
} void addEdge(int from, int to, int dist){
edges.pb((Edge){from, to, dist});
m = edges.sz;
G[from].pb(m-1);
} void dijkstra(int s){
priority_queue<HeapNode> pq;
ms(d, INF); d[s] = 0;
ms(done, 0);
pq.push((HeapNode){0, s});
while(!pq.empty()){
HeapNode x = pq.top(); pq.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i = 0; i < G[u].sz; ++i){
Edge &e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist){
d[e.to] = d[u] + e.dist;
pq.push((HeapNode){d[e.to], e.to});
}
}
}
}
};
Dijkstra dij; int readint(){ int x; scanf("%d", &x); return x; } int main(){
int r1, c1, r2, c2, kase = 0;
while(scanf("%d %d %d %d %d %d", &n, &m, &r1, &c1, &r2, &c2) == 6 && n){
--r1, --r2, --c1, --c2;
for(int r = 0; r < n; ++r){
for(int c = 0; c < m-1; ++c)
g[r][c][RIGHT] = g[r][c+1][LEFT] = readint();
if(r != n-1) for(int c = 0; c < m; ++c)
g[r][c][DOWN] = g[r+1][c][UP] = readint();
}
dij.init(n * m * 8 + 1);
cnt = 0; ms(id, 0);
for(int dir = 0; dir < 4; ++dir) if(cango(r1, c1, dir)) // the edge of source
dij.addEdge(0, ID(r1+dr[dir], c1+dc[dir], dir, 1), g[r1][c1][dir] * 2);
FOR(r, 0, n) FOR(c, 0, m) FOR(dir, 0, 4) if(cango(r, c, inv[dir]))
FOR(newdir, 0, 4) if(cango(r, c, newdir)) FOR(doubled, 0, 2){
int x = r + dr[newdir];
int y = c + dc[newdir];
int v = g[r][c][newdir], newdoubled = 0;
if(dir != newdir){
if(!doubled) v += g[r][c][inv[dir]]; // the old edge double
newdoubled = 1; v += g[r][c][newdir]; // the new edge double
}
dij.addEdge(ID(r, c, dir, doubled), ID(x, y, newdir, newdoubled), v);
}
dij.dijkstra(0);
int ans = INF;
FOR(dir, 0, 4) if(cango(r2, c2, inv[dir]))
for(int doubled = 0; doubled < 2; ++doubled){
int v = dij.d[ID(r2, c2, dir, doubled)];
if(!doubled) v += g[r2][c2][inv[dir]];
ans = min(ans, v);
}
printf("Case %d: ", ++kase);
if(ans == INF) puts("Impossible");
else printf("%d\n", ans);
}
return 0;
}
UVaLive 4128 Steam Roller (多决策最短路)的更多相关文章
- UVALive 4128 Steam Roller(最短路(拆点,多状态))
题意:模拟了汽车的行驶过程,边上的权值为全速通过所消耗的时间,而起步(从起点出发的边).刹车(到终点结束的边).减速(即将拐弯的边).加速(刚完成拐弯的边)这四种不能达到全速的情况,消耗的时间为权值* ...
- UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。
题意: 给一个由n*m个正方形格子组成的矩形,其中每个格子的边都是可以走的,长度给定,规定:如果在进入该路前需要拐弯,或者走完该路需要拐弯,都是需要付出双倍距离的(每条路最多算2倍).问从起点到终点的 ...
- UVa1078 Steam Roller——拆点+最短路
题目链接 思路 把每个点拆成\(5\)个点\(id(x,y),id(x,y)+n,id(x,y)+2*n,id(x,y)+3*n,id(x,y)+4*n\),分别表示到这个点时的方向为上,右,下,左和 ...
- 二分+最短路 uvalive 3270 Simplified GSM Network(推荐)
// 二分+最短路 uvalive 3270 Simplified GSM Network(推荐) // 题意:已知B(1≤B≤50)个信号站和C(1≤C≤50)座城市的坐标,坐标的绝对值不大于100 ...
- 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...
- Delivering Goods UVALive - 7986(最短路+最小路径覆盖)
Delivering Goods UVALive - 7986(最短路+最小路径覆盖) 题意: 给一张n个点m条边的有向带权图,给出C个关键点,问沿着最短路径走,从0最少需要出发多少次才能能覆盖这些关 ...
- UVALive 7302 (最短路)
Probelm Terrorists 题目大意 给一张n个点,m条边的无向图.共有q个询问,每次询问u到v的最短路. n <= 100000 , n-1 <= m <= n + 5 ...
- UVALive 6885 Flowery Trails 最短路枚举
题目连接: http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=129723 题意: 给你一个n点m图的边 1到n有多条最短路 ...
- UVALive 3661 Animal Run(最短路解最小割)
题意:动物要逃跑,工作人员要截断从START(左上角)到END(右下角)的道路,每条边权表示拦截该条道路需要多少工作人员.问最少需要多少人才能完成拦截. 通俗地讲,就是把图一分为二所造成消耗的最小值. ...
随机推荐
- TCP和UDP Client 代码
最近学习要求做网络编程,使用从网上找了一些资料,主要是网络协议的分层等通讯,你可以查看英文版的资料:CScharp网络编程英文版 下面直接给出代码吧,我想一看应该就懂. TCP Client 代码: ...
- bzoj 3144 [Hnoi2013]切糕——最小割
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3144 一根纵轴上切一个点,可以把一根纵轴上的点连成一串来体现.自己的写法是每个点连向前一个点 ...
- Ionic 项目创建
1. Ionic介绍 Ionci 是一个强大的HTML5 应用程序框架. 可以帮助您使用Web技术,如HTML, CSS和Javascript构建原生体验的移动应用程序. Ionic主要关注外观和体验 ...
- Asp.net MVC Comet 推送
一.简介 在Asp.net MVC实现的Comet推送的原理很简单. 服务器端:接收到服务器发送的AJAX请求,服务器端并不返回,而是将其Hold住,待到有东西要通知客户端时,才将这个请求返回. 客户 ...
- while循环-for循环
while true: 无限循环语句 break跳出循环,当count=1000的时候结束循环 count是结束当前循环'''count = 0while True: print("coun ...
- C++ 排序总结
原帖地址 http://kongec.blog.sohu.com/85141353.html 附 六分钟演示15中算法 http://www.guokr.com/post/482666/ 一.插入排 ...
- python xlwt操作excel
- ES6系列_7之箭头函数和扩展
1.默认值 在ES6中给我们增加了默认值的操作相关代码如下: function add(a,b=1){ return a+b; } console.log(add(1)); 可以看到现在只需要传递一个 ...
- AngularJS学习笔记(2)——与用户交互的动态清单列表
与用户交互的动态清单列表 以我之前写的一个清单列表页面作为例子(MVC模式的清单列表效果),优化前代码如下: <!DOCTYPE html> <html ng-app="t ...
- Spring集成的Quartz 并发
以前经常在任务调度程序中使用Spring集成的Quartz,这种方式可以用简单的声明式配置即可实现定时任务,并结合了Spring自身的Bean的管理功能,非常方便.配置样本如下: <bean i ...