题意:模拟了汽车的行驶过程,边上的权值为全速通过所消耗的时间,而起步(从起点出发的边)、刹车(到终点结束的边)、减速(即将拐弯的边)、加速(刚完成拐弯的边)这四种不能达到全速的情况,消耗的时间为权值*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. 【BZOJ】【3275】Numbers

    网络流/最小割 Orz了Jiry_2神犇,蒟蒻网络流建模什么的完全不会啊T_T 按奇偶性来分组实在太巧妙了……然后相关的点之间连边表示只能选其一,来求最小割…… /****************** ...

  2. [CF]codeforces round 369(div2)

    *明早起来再贴代码 A [题意] 给定n*5的方格 将横向的相邻两个变成+输出 [题解] ... B [题意] 一个n*n的正整数矩阵,有且仅有一个数为0 ,在这个位置填上一个数,使得每一列的和 每一 ...

  3. Ubuntu的LTS版本

    Ubuntu的LTS版本什么意思 LTS是长期支持(Long Term Support)的缩写. 我们每六个月制作一个新的Ubuntu桌面和服务器的版本,这意味着你总能拥有开源世界提供的最新最好的应用 ...

  4. 用matlab查找txt文档中的关键字,并把关键字后面的数据存到起来用matlab处理

    用matlab查找txt文档中的关键字,并把关键字后面的数据存到起来用matlab处理 我测了一组数据存到txt文件中,是个WIFI信号强度文档,里面有我们需要得到的数据,有没用的数据,想用matla ...

  5. Kafka之Purgatory Redesign Proposal (翻译)

    Purgatory是Kafka server中处理请求时使用的一个重要的数据结构.正好研究ReplicaManager源码的时候发现了这篇文章,顺便翻译下.由于这个proposal里的很多东西需要看源 ...

  6. Zabbix 集成 OneAlert 实现全方位告警

    1. 前言 告警将重要信息发送给运维「或者其他相关人」,及时发现并且处理问题.在所有开源监控软件里面,Zabbix 的告警方式无疑是最棒的.告警的方式各式各样,从 Email 告警到飞信.139/18 ...

  7. 【C++基础】构造函数

    说说你对构造函数的理解? 构造函数:对象创建时,利用特定的值构造对象(不是构造类),将对象初始化(保证数据成员有初始值),是类的一个public 函数 ①   与类同名 ②   无返回值 ③   声明 ...

  8. Installing Lua in Mac

    Lua is distributed in source form. You need to build it before using it. Building Lua should be stra ...

  9. SQL 中的游标实例

    --声明变量 declare @IMType varchar(10),@IMResourceID varchar(10) --定义游标 declare information_cursor curso ...

  10. Android中JSON数据格式的简单使用

    源码: package com.wangzhu.demo; import java.io.BufferedReader; import java.io.IOException; import java ...