白书上图论例题2
题目大意是 M*N个格子 #不能走
S是起点 T是终点
上北下南左西右东
一开始在S,朝向北,
在每一个格子 可以左转90度 或者右转90度 或者朝向走1格
问从起点到终点 计算重复格子 走5的整数倍个格子到终点 不限制最后朝向 最短时间是多少
就像书上讲的那样
每个点 拆成20个点
(x,y,color,head)
分别表示该点的坐标,走到该点 走过的格子%5,现在的朝向
每次可以向(x,y,color,head-1) (x,y,color,head+1) (x+mx[head],y+my[head],(color+1)%5,head)走
分别对应左转、右转和前进
因为每次操作都是花费1
所以直接bfs也可以 先搜到的终点一定是时间最少的
这样还有一个好处就是不用扔set了 判重也方便
其实这个不用set也可以。。。
发现现在有点依赖stl了。。。
这个题还有一个坑点 就是 每两组数据间输出一个空行
但是最后一组只能有1个空行!
我用spfa写的
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<map> #include<queue> using namespace std; const int lim = 26; const int lin = lim*lim*lim*lim*lim; const int inf = 0x3f3f3f3f; const int mx[4]={-1,0,1,0}; const int my[4]={0,1,0,-1}; int g[lim][lim]; struct node { int x,y,color,head; node() { x=y=color=head=0; } node(int xx,int yy,int col,int hea) { x=xx; y=yy; color=col; head=hea; } bool operator<(const node h) const { if(h.x==x) if(h.y==y) if(h.color==color) return h.head<head; else return h.color<color; else return h.y<y; else return h.x<x; } }; node S,T; map<node,int>mp; queue<node>q; int d[lim*lim*20]; int vis[lim*lim*20]; int fst[lim*lim*20]; int m,n; int r,c; char chin; int _case; void spfa() { while(!q.empty()) q.pop(); memset(d,0x3f,sizeof(d)); memset(vis,0,sizeof(vis)); q.push(S); mp[S]=++m; vis[m]=1; d[m]=0; while(!q.empty()) { node u=q.front(); q.pop(); int uid=mp[u]; vis[uid]=0; int x=u.x; int y=u.y; int color=u.color; int head=u.head; for(int i=-1;i<=1;i+=2) { int hhead=(head+i+4)%4; node v = node(x,y,color,hhead); if(mp[v]==0) { mp[v]=++m; } int vid=mp[v]; if(d[vid]>d[uid]+1) { d[vid]=d[uid]+1; if(!vis[vid]) { vis[vid]=1; q.push(v); } } } int xx=x+mx[head],yy=y+my[head]; int ccolor=(color+1)%5; if(xx>=1 && xx<=r && yy>=1 && yy<=c && g[xx][yy]==1) { node v = node(xx,yy,ccolor,head); if(mp[v]==0) { mp[v]=++m; } int vid=mp[v]; if(d[vid]>d[uid]+1) { d[vid]=d[uid]+1; if(!vis[vid]) { vis[vid]=1; q.push(v); } } } } int ans = inf; for(int k=0;k<=3;k++) { node tt = node(T.x,T.y,0,k); ans=min(ans,d[mp[tt]]); } if(ans==inf) { printf("Case #%d destination not reachable ",_case); } else { printf("Case #%d minimum time = %d sec ",_case,ans); } } int main() { while(scanf("%d%d",&r,&c)==2) { if(r==0 && c==0) return 0; if(_case>=1) printf(" "); m=0; mp.clear(); _case++; memset(fst,-1,sizeof(fst)); for(int i=1;i<=r;i++) { for(int j=1;j<=c;j++) { scanf(" %c",&chin); if(chin=='#') g[i][j]=0; else { g[i][j]=1; if(chin=='S') { S.x=i; S.y=j; S.color=0; S.head=0; } if(chin=='T') { T.x=i; T.y=j; T.color=0; } } } } spfa(); } return 0; }