借鉴了陈峰在训练指南的思路, 表示感谢
提示: 1. 直接求最短路是有困难的, 因为状态不满足独立性 , 所以拆点
2. 将(x , y)细分成 , (x , y , dir , doubled) , 后两个分别为到这个点时的方向、这条边是否两次计算了
3. 将每一个状态用一个id 函数投射到一个具体的数值 , 然后预处理所有状态之间的边(处理好那些double) , 这样求最短路就是一个独立的过程
4. 开头的源点不好把握 , 所以特殊处理 , 将第一次转移拿出来 ; 但结尾的统计是简单的
注意: 为了方便各种mod , 和计算id , 使用从0开始的坐标会更简单 , 如果有人看过训练指南的代码仓库这个题的代码 , 就会发现写的很麻烦 , 这种题目一定要注意 , 充分利用状态 , 不要给自己添麻烦 , 详情见代码
// // main.cpp // UVa 1078 // // Created by Fuxey on 15/10/7. // Copyright © 2015年 corn.crimsonresearch. All rights reserved. // #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <vector> #include <deque> #include <set> #include <map> #include <string> #include <algorithm> #include <list> #include <queue> using namespace std; struct edge { int t , v; edge(int t = 0, int v = 0):t(t),v(v){} }; struct state { int p , d; state(int p = 0, int d = 0):p(p),d(d){} bool operator <(const state& b)const { return d>b.d; } }; const int maxnode= 8e4+1e3; const int INF = 1<<29; int e[110][110][2]; int dx[]={0,0,1,-1}; int dy[]={1,-1,0,0}; int rev[]={1,0,3,2}; int n , m , sx , sy , ex , ey; vector<edge> g[maxnode]; int d[maxnode] , book[maxnode]; int id(int x , int y , int i, int j){ if(!(x>=0 && x<n && y>=0 && y<m)) return -1; return ((x*m+y)*4+i)*2+j;} // i ->dir , j-?doubled void reid(int p) { int d = p%2; p/=2; int dir = p%4; p/=4; int y = p%m; int x = p/m; cout<<x<<" "<<y<<" "<<dir<<" "<<d<<endl; } int main(int argc, const char * argv[]) { int Case=0; while(cin>>n>>m>>sx>>sy>>ex>>ey && n+m) { sx--; sy--; ex--; ey--; for(int i=0;i<n;i++) { for(int j=0;j<m-1;j++) scanf("%d",&e[i][j][0]); if(i!=n-1) for(int j=0;j<m;j++) scanf("%d",&e[i][j][1]); } for(int i=0;i<8*n*m;i++) g[i].clear(); for(int i=0;i<n;i++) for(int j=0;j<m;j++) for(int dir = 0;dir<4;dir++) for(int d=0;d<2;d++) for(int dir2 = 0;dir2<4;dir2++) for(int d2=0;d2<2;d2++) { int p1 = id(i, j, dir, d); int p2 = id(i+dx[dir2], j+dy[dir2], dir2, d2); if(p2==-1) continue; if((d==0 || d2==0) && dir!=dir2) continue; int ndir = dir2 , X = i , Y = j , V; if(ndir!=0 && ndir!=2){ ndir = rev[ndir]; X = i+dx[dir2]; Y = j+dy[dir2]; } ndir = (ndir==0?0:1); V = e[X][Y][ndir]; if(V==0) continue; if(d2) V*=2; g[p1].push_back(edge(p2 , V)); } fill(d, d+8*n*m, INF); fill(book, book+8*n*m, 0); priority_queue<state> q; int ss = id(sx, sy, 0, 1); for(int i=0;i<g[ss].size();i++) if(g[ss][i].t%2) { int t = g[ss][i].t; d[t] = g[ss][i].v; q.push(state(t , d[t])); } while(!q.empty()) { state u = q.top(); q.pop(); if(book[u.p]) continue; book[u.p] = 1; for(int i=0;i<g[u.p].size();i++) { int t = g[u.p][i].t; int v = g[u.p][i].v; if(d[t] > d[u.p]+v) { d[t] = d[u.p]+v; q.push(state(t , d[t])); } } } int res = INF; for(int dir = 0;dir<4;dir++) { int p = id(ex, ey, dir, 1); res = min(res, d[p]); } cout<<"Case "<<++Case<<": "; if(res==INF) cout<<"Impossible\n"; else cout<<res<<endl; } return 0; }
文章有任何纰漏 , 或者有任何问题 , 请告知博主: QQ:812483101