B组
T1.锅题
upd:改数据了,出题人
T2.run 小S练跑步
BFS搜索,注意一个地方。
记录的mn[x][y]为到当前点最少拐弯次数,当新的cost>mn[x][y]剪枝,而不是大于等于,等于的时候可能方向不同,再加一个数组lst[x][y]表示在取到mn时的方向,若cost==mn且当前方向==lst,则跳过。
其实类似一个vis[x][y][4],记录这个状态是否在队列中,类似SPFA。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=512; int n,m; int mp[MAXN*MAXN]; int lst[MAXN*MAXN]; int mn[MAXN*MAXN]; struct Node{ int x,y,dir,cost; }node,top; queue<Node> Q; int dx[5]={0,0,1,0,-1}; int dy[5]={0,1,0,-1,0}; int tran[MAXN]; int ans=1<<29; bool succ=0; char s[MAXN]; int main(){ freopen("run.in","r",stdin); freopen("run.out","w",stdout); memset(mn,0x3f,sizeof(mn)); n=rd();m=rd(); tran['R']=1; tran['D']=2; tran['L']=3; tran['U']=4; tran['S']=5; for(register int i=1;i<=n;i++){ scanf("%s",s+1); for(register int j=1;j<=m;j++){ mp[(i<<9)+j]=tran[s[j]]; } } node.x=1;node.y=1;node.cost=0;node.dir=0; Q.push(node); while(!Q.empty()){ top=Q.front();Q.pop(); register int x=top.x,y=top.y,cost=top.cost,dir=top.dir; if(x==n&&y==m){ ans=min(ans,cost); succ=1; continue; } if(mp[(x<<9)+y]==5) continue; register int nx,ny; for(register int k=1;k<=4;k++){ if(k==mp[(x<<9)+y]) continue; nx=x+dx[k];ny=y+dy[k]; int v=(nx<<9)+ny; if(!mp[v]) continue; if(mn[v]<cost+(k!=dir)) continue; if(mn[v]==cost+(k!=dir)&&lst[(nx<<9)+ny]==k) continue; lst[v]=k; mn[v]=cost+(k!=dir); node.x=nx;node.y=ny; node.dir=k;node.cost=cost+(k!=dir); Q.push(node); } } if(succ) cout<<ans-1; else puts("No Solution"); return 0; }