题意:模拟了汽车的行驶过程,边上的权值为全速通过所消耗的时间,而起步(从起点出发的边)、刹车(到终点结束的边)、减速(即将拐弯的边)、加速(刚完成拐弯的边)这四种不能达到全速的情况,消耗的时间为权值*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(最短路(拆点,多状态))的更多相关文章

  1. UVaLive 4128 Steam Roller (多决策最短路)

    题意:给定一个图,r 根横线, c 根竖线.告诉你起点和终点,然后从起点走,每条边有权值,如果是0,就表示无法通行.走的规则是:如果你在下个路要转弯,会使这段路的时间加倍,但是如果一条路同时是这样,那 ...

  2. UVALive 4128 Steam Roller 蒸汽式压路机(最短路,变形) WA中。。。。。

    题意: 给一个由n*m个正方形格子组成的矩形,其中每个格子的边都是可以走的,长度给定,规定:如果在进入该路前需要拐弯,或者走完该路需要拐弯,都是需要付出双倍距离的(每条路最多算2倍).问从起点到终点的 ...

  3. 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\),分别表示到这个点时的方向为上,右,下,左和 ...

  4. HDU 4725 The Shortest Path in Nya Graph(最短路拆点)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725 题意:n个点,某个点属于某一层.共有n层.第i层的点到第i+1层的点和到第i-1层的点的代价均是 ...

  5. BZOJ 3931 网络吞吐量(最短路+拆点最大流)

    3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1607  Solved: 652 [Submit][St ...

  6. UVALive 6885 Flowery Trails 最短路枚举

    题目连接: http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=129723 题意: 给你一个n点m图的边 1到n有多条最短路 ...

  7. UVALive 6885 Flowery Trails 最短路

    Flowery Trails 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid= ...

  8. 【ACM】那些年,我们挖(WA)过的最短路

    不定时更新博客,该博客仅仅是一篇关于最短路的题集,题目顺序随机. 算法思想什么的,我就随便说(复)说(制)咯: Dijkstra算法:以起始点为中心向外层层扩展,直到扩展到终点为止.有贪心的意思. 大 ...

  9. 【bzoj3931】[CQOI2015]网络吞吐量 最短路+最大流

    题目描述 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的地,路由器需要选择最优的路径转发 ...

随机推荐

  1. 安装 SQL SERVER PROFILER

    SQL SERVER 2008 R2 (10.50.40) 版本,安装 SQL SERVER PROFILER:通过 command prompt,使用以下命令:setup.exe /FEATURES ...

  2. [转载]淘宝API调用 申请 获取session key

    http://www.cnblogs.com/zknu/archive/2013/06/14/3135527.html 在调用淘宝的API时,我们都会用到appkey,appsecret,appses ...

  3. C# textbox 滚动条 随文本输入 滚动

    tb_Log.SelectionStart = tb_Log.Text.Length;//设置光标位置 tb_Log.ScrollToCaret();//随文本输入 滚动

  4. 利用vim阅读源代码一个好用的工具

    阅读源代码时常常遇到找变量,函数定义的问题.vim为我们提供了一个好用的工具,ctags. 安装 ctags. 在 libvirt的源代码根目录运行 ctags -R . vim -t virConn ...

  5. 【面试题002】java实现的单例模式,c++实现单例模式,实现禁止拷贝

    [面试题002]java实现的单例模式,c++实现单例模式,实现禁止拷贝  一 c++实现单例模式 保证一个类,在一个程序当中只有一个对象,只有一个实例,这个对象要禁止拷贝,注意这里要区别于java. ...

  6. Observer Pattern

    Motivation We can not talk about Object Oriented Programming without considering the state of the ob ...

  7. C# 实现:将一个文件夹下的.png图片全部移动到另一个文件夹

    如题,代码如下: using System; using System.IO; public class FileMove { public FileMove() { // TODO: } // co ...

  8. hdu 4578 Transformation 线段树

    没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...

  9. Secret and Whisper

    这两个应用都是以匿名方式向朋友分享信息. 36氪的网友评论到: Whisper 的厉害之处在于给年轻人提供了一个释放压力的地方,比如说他去年陪孩子看病,这种经历不愿意放到 Facebook 上,但是他 ...

  10. jndi配置数据源

    jndi(java Naming and DirectoryInterface,java命名和目录接口)是一组在Java应用中访问命名和目录服务的API. 命名服务将名称和对象联系起来,使得我们可以用 ...