模拟赛20181015 Uva1078 bfs+四维dp
题意:一张网格图,多组数据,输入n,m,sx,sy,tx,ty大小,起终点
接下来共有2n-1行,奇数行有m-1个数,表示横向的边权,偶数行有m个数,表示纵向的边权
样例输入:
4 4 1 1 4 4
10 10 10
9 0 0 10
0 0 0
9 0 0 10
0 9 0 10
0 9 9
2 2 1 1 2 2
0
1 1
0
0 0 0 0 0 0
样例输出:
Case 1: 100
Case 2: Impossible
我们发现此题的特点在于允许转向,也就是说我们可以将转向的状态利用一维表示出来以进行转移
同时由于起终点也需要*2,我们干脆新开两维,一维表示是否*2,另一维表示当前已经操作后面对的方向
利用spfa进行转移即可
#include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<=y;i++) using namespace std; const int NN=20000; const int NNN=80000; const int inf=100000000; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} int g[NN][4]; int d[NNN]; bool vis[NNN]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int n,m,sx,sy,tx,ty,x,y,t,idx,w; struct node{int x,y,t;};queue<node> q; inline int calc(int x,int y){return (x-1)*m+(y-1);} inline int calc(int x,int y,int t){return calc(x,y)*5+t;} bool check(int x,int y){return 1<=x&&x<=n&&1<=y&&y<=m;} int main(){ while(scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty)!=EOF&&n&&m){ rep(i,1,2*n-1) if(i&1) rep(y,1,m-1){ x=(i+1)/2,w=read();if(!w) w=inf; g[calc(x,y)][0]=g[calc(x,y+1)][1]=w;} else rep(y,1,m){ x=i/2,w=read();if(!w) w=inf; g[calc(x,y)][2]=g[calc(x+1,y)][3]=w;} //t代表的状态是身后已经加的边的状态 memset(d,60,sizeof d); d[calc(sx,sy,4)]=0; vis[calc(sx,sy,4)]=1; q.push((node){sx,sy,4}); while(!q.empty()){ x=q.front().x; y=q.front().y; t=q.front().t;q.pop(); vis[calc(x,y,t)]=0; // 4 前后都要二倍 if(t<4){// i-i int xx=x+dx[t],yy=y+dy[t]; if(!check(xx,yy)) continue; int w=g[calc(x,y)][t]; if(d[calc(xx,yy,t)]>d[calc(x,y,t)]+w){ d[calc(xx,yy,t)]=d[calc(x,y,t)]+w; if(!vis[calc(xx,yy,t)]) vis[calc(xx,yy,t)]=1,q.push((node){xx,yy,t});} w=w*2;//i-4 if(d[calc(xx,yy,4)]>d[calc(x,y,t)]+w){ d[calc(xx,yy,4)]=d[calc(x,y,t)]+w; if(!vis[calc(xx,yy,4)]) vis[calc(xx,yy,4)]=1,q.push((node){xx,yy,4});} }else{ for(int i=0;i<=3;i++){ int xx=x+dx[i],yy=y+dy[i]; if(!check(xx,yy)) continue; int w=g[calc(x,y)][i]*2; //4 是转向所以w跟随i变化 // 4-i if(d[calc(xx,yy,i)]>d[calc(x,y,t)]+w){ d[calc(xx,yy,i)]=d[calc(x,y,t)]+w; if(!vis[calc(xx,yy,i)]) vis[calc(xx,yy,i)]=1,q.push((node){xx,yy,i});} // 4-4 if(d[calc(xx,yy,4)]>d[calc(x,y,t)]+w){ d[calc(xx,yy,4)]=d[calc(x,y,t)]+w; if(!vis[calc(xx,yy,4)]) vis[calc(xx,yy,4)]=1,q.push((node){xx,yy,4}); } } }/* i-i 正常直走 i-4 决策 转弯的第一条边 到达终点 4-i 决策 转弯的第二条边 起点结束 4-4 决策 转弯到终点 决策 连续转弯 */ }// 三维状态 二维权值 int ans=d[calc(tx,ty,4)]; if(ans>=inf) printf("Case %d: Impossible\n",++idx); else printf("Case %d: %d\n",++idx,ans); }return 0; }
完结撒花