UVALive 4128 Steam Roller(最短路(拆点,多状态))
题意:模拟了汽车的行驶过程,边上的权值为全速通过所消耗的时间,而起步(从起点出发的边)、刹车(到终点结束的边)、减速(即将拐弯的边)、加速(刚完成拐弯的边)这四种不能达到全速的情况,消耗的时间为权值*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]网络吞吐量 最短路+最大流
题目描述 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的地,路由器需要选择最优的路径转发 ...
随机推荐
- Chrome浏览器下调试SASS
网上说的方案各有各的说法,尝试多个才找到有效方案,为避免后来者麻烦,现在讲讲如何调试 笔者ruby版本为3.4.19,因为sass文件的编译是需要ruby环境的,使用sass前需要先安装! 第一步(核 ...
- CentOS安装RockMongo
rockmongo官网下载页面在这里: http://rockmongo.com/downloads 找到最新版本的下载链接,一般第一个就是: 右键复制url,比如说是这个: http://rockm ...
- Roy Li的学习和成长自传
我不知道自己是什么时候从哪里来到这个世界上的,也许是石头里蹦出来的,也许是女娲捏出来的,上帝造出来的.上溯到我记忆的最前端,抱着我的好象 是一个女人,穿着白衣服,白得象石灰一样的那种.以至于后来我被告 ...
- docker设置代理
在天朝使用docker需要FQ. 下面给出docker的代理方式: HTTP_PROXY=http://10.167.251.83:8080 docker -d
- 国产神通数据库操作备忘(Linux)
最近接触到国产神通数据库的一个项目,发现这个数据库还是挺有技术含量的,看起来做的还不错. 1.启动停止 在终端窗口中输入以下命令启动数据库: # /etc/init.d/oscardb_<数据库 ...
- pl/sql tutorial
http://plsql-tutorial.com/plsql-procedures.htm What is PL/SQL? PL/SQL stands for Procedural Language ...
- POJ1144 Network 无向图的割顶
现在打算重新学习图论的一些基础算法,包括像桥,割顶,双连通分量,强连通分量这些基础算法我都打算重敲一次,因为这些量都是可以用tarjan的算法求得的,这次的割顶算是对tarjan的那一类算法的理解的再 ...
- 在mac上安装hadoop伪分布式
换了macbook pro之后,要重新安装hadoop,但是mac上的jdk跟windows上的不同,导致折腾了挺久的,现在分享出来,希望对大家有用. 一:下载jdk 选择最新版本下载,地址:http ...
- PowerDesigner修改设计图中文字的字体大小等样式
设计图中默认的字体是对英文比较合适的,中文就看不清楚了,特别不美观.但是可以通过修改“Display Preferences”适应我们的汉字. 我使用的PowerDesigner版本是15.1(测试版 ...
- HTML5+开发移动app教程3-mui开发示例
下面就开始一个简答的例子,以及mui相关内容 mui 官网:http://dcloudio.github.io/mui/ 说明:http://dev.dcloud.net.cn/mui/ui/inde ...