Steam Roller UVALive
来源:互联网 发布:网络光纤收发器 编辑:程序博客网 时间:2024/05/03 04:01
Steam Roller UVALive - 4128
图论·最短路
题目大意:
给你一张格子图,r根横线,c根竖线。告诉你起点和终点,然后从起点走,每条边有权值,如果是0,就表示无法通行。走的规则是(通俗点):车子的惯性比较大,如果你在下个路口要转弯,那么后半段就开慢了,好转弯,转弯完了之后,你要加速,那么前半段就慢了,这两种情况都会使这段路的时间加倍,但是如果一条路同时是这样,那么也只算两倍。起点这终点一个启动,一个是制动,那么和他们相连的第一条边也算两倍。问你最短时间,如果不行,就输出 “Impossible” 。
题解:
设计状态:节点(x,y,lastdir,doubled)表示在点(x,y),上一次走的方向是lastdir,以及刚刚走过来的这条边有没有加倍。
然后按照题意连边,具体请参见代码。
但是注意:这里有坑,就是到达终点的时候,由于边权加倍规则的存在,那么到达终点了可以再往前走一段,再回来,也就是说,本来不是说到达终点的边也要加倍,但是并不是在更新的时候直接判断加倍,这样会有问题,我的处理方式是,终点和其他点的处理方式一样,从队列里拿粗来的时候,判断是不是终点,然后再看 doubled ,就是到达终点的这条边正常模式下有没有加倍,如果没有就加倍,然后更新 ans。
蒙蒙一开始自己写了一份建好图然后跑spfa的,没调过。
代码能力太弱。。。
然后抄了一份神题解,在dij的时候再处理边连向哪里和边权,感觉很简洁。
而且大神直接把上一条边的边权和这个点的d[]存在Node里面,不是像蒙蒙那样每次用奇奇怪怪的函数去找(我是zz不要管我)。
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int N = 105;const int INF = 0x3f3f3f3f;int n,m,sx,sy,tx,ty;struct Edge{ int x1,y1,x2,y2; int val,dir; int next;}e[N*N*4];int head[N][N]; int ec;void clear(){ memset(head,0,sizeof(head)); ec=0; }void add(int x1,int y1,int x2,int y2,int val,int dir){ ec++; e[ec].x1=x1, e[ec].y1=y1; e[ec].x2=x2, e[ec].y2=y2; e[ec].val=val; e[ec].dir=dir; e[ec].next=head[x1][y1]; head[x1][y1]=ec;}struct Node{ int x,y,val; int lastdir,lastval,doubled; Node(int a,int b,int v,int ld,int lv,int bo){ x=a; y=b; val=v; lastdir=ld; lastval=lv; doubled=bo; } bool operator < (const Node &tp) const { return val > tp.val; }};int done[N][N][5][3];int d[N][N][5][3];int ans;void dij(){ priority_queue<Node> q; memset(done,0,sizeof(done)); memset(d,0x3f,sizeof(d)); d[sx][sy][4][1]=0; q.push(Node(sx,sy,0,4,0,1)); while(!q.empty()){ Node u=q.top(); q.pop(); if(u.x==tx && u.y==ty){ int tp=u.val; if(!u.doubled){ tp+=u.lastval; } ans=min(ans,tp); } if(done[u.x][u.y][u.lastdir][u.doubled]) continue; done[u.x][u.y][u.lastdir][u.doubled]=1; for(int i=head[u.x][u.y];i;i=e[i].next){ int xx=e[i].x2; int yy=e[i].y2; int val=e[i].val; int dir=e[i].dir; int oldcnt=0; if(dir!=u.lastdir && u.doubled==0) oldcnt=1; int newcnt=1,nextdoubled=0; if(dir!=u.lastdir){ newcnt=2; nextdoubled=1; } int tp=d[u.x][u.y][u.lastdir][u.doubled]+newcnt*val+oldcnt*u.lastval; if(d[xx][yy][dir][nextdoubled]>tp){ d[xx][yy][dir][nextdoubled]=tp; q.push(Node(xx,yy,tp,dir,val,nextdoubled)); } } }}int main(){ freopen("a.in","r",stdin); int cas=0; while(~scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty)){ if(n+m==0) break; sx--; sy--; tx--; ty--; clear(); for(int i=0;i<2*n-1;i++){ int val; if(i&1){ for(int j=0;j<m;j++){ scanf("%d",&val); if(val==0) continue; add(i/2+1,j,i/2,j,val,3); add(i/2,j,i/2+1,j,val,1); } } else{ for(int j=0;j<m-1;j++){ scanf("%d",&val); if(val==0) continue; add(i/2,j,i/2,j+1,val,0); add(i/2,j+1,i/2,j,val,2); } } } ans=INF; dij(); printf("Case %d: ",++cas); if(ans>=INF) puts("Impossible"); else printf("%d\n",ans); }}
阅读全文
0 0
- Steam Roller UVALive
- UVALive 4128 Steam Roller
- UVALive 4128 Steam Roller(多状态最短路)
- UVa 1078 Steam Roller
- UVA 1078 - Steam Roller(最短路)
- uva 1078 - Steam Roller(最短路)
- UVALive4128[Steam Roller] dijkstra+拆点
- La 4128 Steam Roller 状态图上的Dijkstra
- Uva 1078 Steam Roller(多状态最短路)
- steam
- steam
- roller部署
- Roller(Weblogic)
- roller blog
- Apache Roller
- 安装 Roller
- roller使用手册
- Roller Coaster
- hadoop 单词个数及所处文件位置统计
- 如何设置自己的jupyter服务器的密码
- 不熟悉的HTML标签整理
- HashTable
- BMP格式详解
- Steam Roller UVALive
- Ubuntu14.04+Slam(模拟topic)
- 史上最全图像识别特征描述及代码
- KMP
- [LeetCode]38. Count and Say
- Math对象
- 简单加解密(三)
- 整理第十届河南省ACM省赛正解
- JDK-db