题意:模拟了汽车的行驶过程,边上的权值为全速通过所消耗的时间,而起步(从起点出发的边)、刹车(到终点结束的边)、减速(即将拐弯的边)、加速(刚完成拐弯的边)这四种不能达到全速的情况,消耗的时间为权值*2。问从起点到终点所消耗的最少时间。
这道题主要是建图,很复杂,无耻地照着书上的代码码了一遍。让状态搞糊涂了= =
注意:
1、grid[][][4]记录了点的上下左右四条边的权值,id[][][4][2]记录各个点。
2、到一个点的最短路可以是路过这个点再折返回来,e.g:1->2 c=17,2->3 c=4,从1->2的最短路为17+8+8=33<34
3、原图总点数上限100*100,而拆点后共有8*100*100个点,狠狠地RE了一发。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std; const int MAXN=;
const int maxr=,maxc=;
const int INF =1e9; const int UP=,LEFT=,DOWN=,RIGHT=;
const int inv[]={,,,};
const int dr[]={-,,,};
const int dc[]={,-,,}; struct Edge{
int u,v,c;
}; struct HeapNode{
int c,u;
bool operator < (const HeapNode rhs)const {
return c>rhs.c;
}
}; struct Dijkstra{
int n,m;
vector<Edge>edges;
vector<int>G[MAXN];
bool vis[MAXN];
int d[MAXN],p[MAXN]; void init(int n)
{
this->n=n;
for(int i=;i<n;i++)
G[i].clear();
edges.clear();
} void add(int u,int v,int c)
{
edges.push_back((Edge){u,v,c});
m=edges.size();
G[u].push_back(m-);
} void dijkstra(int st)
{
priority_queue<HeapNode>q;
for(int i=;i<n;i++)
d[i]=INF;
d[st]=;
memset(vis,,sizeof(vis));
q.push((HeapNode){,st});
while(!q.empty())
{
HeapNode x=q.top();q.pop();
int u=x.u;
if(vis[u])
continue;
vis[u]=true;
int sz=G[u].size();
for(int i=;i<sz;i++)
{
Edge e=edges[G[u][i]];
if(d[e.v]>d[u]+e.c){
d[e.v]=d[u]+e.c;
q.push((HeapNode){d[e.v],e.v});
}
}
}
}
}; int grid[maxr][maxc][]; int n,id[maxr][maxc][][]; int ID(int r,int c,int dir,int doubled)
{
int& x=id[r][c][dir][doubled];
if(x==)x=++n;
return x;
} int R,C; bool cango(int r,int c,int dir)
{
if(r<||r>=R||c<||c>=C)
return false;
return grid[r][c][dir]>;
} Dijkstra solver; int readint()
{
int x;
scanf("%d",&x);
return x;
} int main()
{
int r1,c1,r2,c2,kase=;
while(scanf("%d%d%d%d%d%d",&R,&C,&r1,&c1,&r2,&c2)==&&R)
{
r1--;c1--;r2--;c2--;
memset(grid,,sizeof(grid));
for(int r=;r<R;r++)//每次更新点(r,c)的下方和右方的边
{
for(int c=;c<C-;c++)
grid[r][c][RIGHT]=grid[r][c+][LEFT]=readint();
if(r!=R-)
for(int c=;c<C;c++)
grid[r][c][DOWN]=grid[r+][c][UP]=readint();
} solver.init(R*C*+); n=;
memset(id,,sizeof(id)); for(int dir=;dir<;dir++)//对起点做double
if(cango(r1,c1,dir))
solver.add(,ID(r1+dr[dir],c1+dc[dir],dir,),grid[r1][c1][dir]*); for(int r=;r<R;r++)//要把所有点都处理完整,不能到r2,c2就结束
for(int c=;c<C;c++)
for(int dir=;dir<;dir++)
if(cango(r,c,inv[dir]))
//为什么是inv?grid[r][c][inv[dir]]是点(r,c)沿inv[dir]方向到点x的边权,同样也是点x->点(r,c)的边权:老边
//而区别在于判断进入(r,c)的边,与出(r,c)进(new,r,newc)的边方向是否一致
for(int newdir=;newdir<;newdir++)
if(cango(r,c,newdir))
for(int doubled=;doubled<;doubled++){
int newr=r+dr[newdir];
int newc=c+dc[newdir];
int v=grid[r][c][newdir],newdoubled=;
if(dir!=newdir){//若方向不一致,两条边都要加倍
if(!doubled)//对于前一条边分两种情况讨论:已经double(之前已经加速或起步),未double
v+=grid[r][c][inv[dir]];//
newdoubled=;
v+=grid[r][c][newdir];
}
solver.add(ID(r,c,dir,doubled),ID(newr,newc,newdir,newdoubled),v);
//若方向一致,连到newdouble==0的两条边权值相同
//否则,连到newdouble==1的两条边相差grid[r][c][inv[dir]],即分开讨论老边是否已加倍,由于最后求最短路,不影响
}
solver.dijkstra(); int ans=INF;
for(int dir=;dir<;dir++)//从与终点(r2,c2)相连的八个状态中取最小值
if(cango(r2,c2,inv[dir]))
for(int doubled=;doubled<;doubled++)
{
int v=solver.d[ID(r2,c2,dir,doubled)];
if(!doubled)
v+=grid[r2][c2][inv[dir]];
ans=min(ans,v);
} printf("Case %d: ",++kase);
if(ans==INF)
printf("Impossible\n");
else
printf("%d\n",ans);
}
return ;
}
后记:
这里的数组id[][][][],以及函数 ID()的处理很值得学习一下。在处理多状态等复杂情况是很实用。
用这个方法自己写了一道题,一遍就通过了样例,好有成就感,可惜uva在这道题上又挂了= =
UVALive 4128 Steam Roller(最短路(拆点,多状态))的更多相关文章
-
UVaLive 4128 Steam Roller (多决策最短路)
题意:给定一个图,r 根横线, c 根竖线.告诉你起点和终点,然后从起点走,每条边有权值,如果是0,就表示无法通行.走的规则是:如果你在下个路要转弯,会使这段路的时间加倍,但是如果一条路同时是这样,那 ...
-
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\),分别表示到这个点时的方向为上,右,下,左和 ...
-
HDU 4725 The Shortest Path in Nya Graph(最短路拆点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725 题意:n个点,某个点属于某一层.共有n层.第i层的点到第i+1层的点和到第i-1层的点的代价均是 ...
-
BZOJ 3931 网络吞吐量(最短路+拆点最大流)
3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 1607 Solved: 652 [Submit][St ...
-
UVALive 6885	 Flowery Trails 最短路枚举
题目连接: http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=129723 题意: 给你一个n点m图的边 1到n有多条最短路 ...
-
UVALive 6885 Flowery Trails 最短路
Flowery Trails 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid= ...
-
【ACM】那些年,我们挖(WA)过的最短路
不定时更新博客,该博客仅仅是一篇关于最短路的题集,题目顺序随机. 算法思想什么的,我就随便说(复)说(制)咯: Dijkstra算法:以起始点为中心向外层层扩展,直到扩展到终点为止.有贪心的意思. 大 ...
-
【bzoj3931】[CQOI2015]网络吞吐量 最短路+最大流
题目描述 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的地,路由器需要选择最优的路径转发 ...
随机推荐
-
SubVersion Ubuntu
UbuntuサーバにSubversionを入れる Linux, 開発ツール | Ubuntuサーバが無事に動いたので.続いてSubversionを入れてみる. こんな感じの環境を考える. Apa ...
-
Android之数据库的创建
一.SQLite介绍 SQLite 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP ...
-
Telerik_2012_Q3 RadGrid 汉化
ChineseRadGridLocalizationProvider.cs using System; using System.Collections.Generic; using System.L ...
-
Android Notivation的使用
官方帮助文档:http://wear.techbrood.com/guide/topics/ui/notifiers/notifications.html 博文推荐:http://blog.csdn. ...
-
angular的小实例
主要是使用了angular的指令. 学习地址:http://www.runoob.com/angularjs/angularjs-tutorial.html 1. 效果: 输入数据剩余字数会相应减少, ...
-
python运算符与数据类型
python运算符 Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 以下假设变量: a=10,b=20: ...
-
Apache rewrite地址重写
Apache-rewrite+13个经典案例Apache 重写规则的常见应用(rewrite)一:目的 如何用Apache重写规则来解决一些常见的URL重写方法的问题,通过常见的 实例给用户一些使用重 ...
-
C++中的static关键字总结
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 1.面向过程设计中的st ...
-
MVC分别代表的含义
MVC 是一种将应用程序的逻辑层和表现层进行分离的方法.ThinkPHP 也是基于MVC设计模式的.MVC只是一个抽象的概念,并没有特别明确的规定,ThinkPHP中的MVC分层大致体现在:模型(M) ...
-
python -keras
Numpy 1. np. shape np.reshape np.prod() astype() dtype() From keras.layers import Input Input():用来实例 ...