藍橋杯-演算法提高 學霸的迷宮(BFS-倒向追蹤輸出移動方向)
演算法提高 學霸的迷宮
時間限制:1.0s 記憶體限制:256.0MB
問題描述
學霸搶走了大家的作業,班長為了幫同學們找回作業,決定去找學霸決鬥。但學霸為了不要別人打擾,住在一個城堡裡,城堡外面是一個二維的格子迷宮,要進城堡必須得先通過迷宮。因為班長還有妹子要陪,磨刀不誤砍柴功,他為了節約時間,從線人那裡搞到了迷宮的地圖,準備提前計算最短的路線。可是他現在正向妹子解釋這件事情,於是就委託你幫他找一條最短的路線。
輸入格式
第一行兩個整數n, m,為迷宮的長寬。
接下來n行,每行m個數,數之間沒有間隔,為0或1中的一個。0表示這個格子可以通過,1表示不可以。假設你現在已經在迷宮座標(1,1)的地方,即左上角,迷宮的出口在(n,m)。每次移動時只能向上下左右4個方向移動到另外一個可以通過的格子裡,每次移動算一步。資料保證(1,1),(n,m)可以通過。
接下來n行,每行m個數,數之間沒有間隔,為0或1中的一個。0表示這個格子可以通過,1表示不可以。假設你現在已經在迷宮座標(1,1)的地方,即左上角,迷宮的出口在(n,m)。每次移動時只能向上下左右4個方向移動到另外一個可以通過的格子裡,每次移動算一步。資料保證(1,1),(n,m)可以通過。
輸出格式
第一行一個數為需要的最少步數K。
第二行K個字元,每個字元∈{U,D,L,R},分別表示上下左右。如果有多條長度相同的最短路徑,選擇在此表示方法下字典序最小的一個。
第二行K個字元,每個字元∈{U,D,L,R},分別表示上下左右。如果有多條長度相同的最短路徑,選擇在此表示方法下字典序最小的一個。
樣例輸入
Input Sample 1:
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
樣例輸出
Output Sample 1:
4
RDRD
Output Sample 2:
4
DDRR
4
RDRD
Output Sample 2:
4
DDRR
資料規模和約定
有20%的資料滿足:1<=n,m<=10
有50%的資料滿足:1<=n,m<=50
有50%的資料滿足:1<=n,m<=50
有100%的資料滿足:1<=n,m<=500。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 600
#define INF 0xfffffff
int n,m;
bool ma[MAXN][MAXN],vis[MAXN][MAXN];//存迷宮地圖、標記是否訪問過
int step[MAXN][MAXN],dir[MAXN][MAXN];//步數、當前位置的移動方向
char ans[MAXN];//從起點到終點總的移動方向
int d[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};//移動方向
struct Node
{
int x,y;//座標
} s,e,pre[MAXN][MAXN];//起終點、當前位置的前一個位置的座標
char shift(int t)//輸出移動方向
{
if(t==0) return 'U';
else if(t==1) return 'D';
else if(t==2) return 'L';
else if(t==3) return 'R';
}
void path()//從e.x和e.y開始倒推出路徑
{
int cnt=0;
ans[cnt++]=shift(dir[e.x][e.y]);//儲存移動方向
int tx=pre[e.x][e.y].x;//求出當前位置的前一個位置的座標
int ty=pre[e.x][e.y].y;
while(1)
{
if(tx==0&&ty==0) break;//追尋到了起點之前
//cout<<dir[tx][ty];
ans[cnt++]=shift(dir[tx][ty]);//儲存移動方向
int ax=pre[tx][ty].x;//為了防止tx更新對ty產生影響而先用臨時變數儲存
int ay=pre[tx][ty].y;
tx=ax;
ty=ay;
}
for(int i=cnt-2; i>=0; --i)//忽略掉起點
cout<<ans[i];//倒向追蹤輸出方向
cout<<endl;
}
bool valid(int x,int y)
{
if(vis[x][y]==true||ma[x][y]==true||x<=0||x>n||y<=0||y>m) return false;
return true;
}
void bfs()
{
queue <Node> q;
q.push(s);
vis[s.x][s.y]=true;
bool flag=false;
while(!q.empty())
{
if(flag) break;
Node t=q.front();
q.pop();
for(int i=0; i<4; ++i)
{
Node a;
a.x=t.x+d[i][0];
a.y=t.y+d[i][1];
if(a.x==e.x&&a.y==e.y)//到達終點
{
vis[a.x][a.y]=flag=true;
step[a.x][a.y]=step[t.x][t.y]+1;
pre[a.x][a.y].x=t.x;
pre[a.x][a.y].y=t.y;
dir[a.x][a.y]=i;
cout<<step[e.x][e.y]<<endl;//輸出步數
path();
break;
}
if(valid(a.x,a.y))//合法
{
vis[a.x][a.y]=true;//標記已經訪問
step[a.x][a.y]=step[t.x][t.y]+1;//步數更新
pre[a.x][a.y].x=t.x;//前向座標更新
pre[a.x][a.y].y=t.y;
dir[a.x][a.y]=i;//方向更新
q.push(a);//入隊
}
}
}
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("G:/cbx/read.txt","r",stdin);
//freopen("G:/cbx/out.txt","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;//行列
memset(ma,false,sizeof(ma));//初始化
memset(vis,false,sizeof(vis));
memset(step,0,sizeof(step));
memset(dir,-1,sizeof(dir));
memset(pre,-1,sizeof(Node)*MAXN);
memset(ans,'\0',sizeof(ans));
for(int i=1; i<=n; ++i)
{
char c[MAXN];//一行行讀入處理
cin>>c;
int cnt=0;
for(int j=1; j<=m; ++j)
ma[i][j]=c[cnt++]-'0';
}
s.x=s.y=1;//起點
e.x=n,e.y=m;//終點
bfs();
return 0;
}
相關文章
- [Java] 藍橋杯ADV-147 演算法提高 學霸的迷宮Java演算法
- 藍橋杯-走迷宮(BFS)
- 藍橋杯-迷宮(BFS+DFS)
- 試題集—— 演算法提高 學霸的迷宮演算法
- 藍橋杯-地宮取寶
- 藍橋杯演算法提高——字串匹配(Java)演算法字串匹配Java
- 藍橋杯 演算法提高 字串壓縮演算法字串
- [藍橋杯][演算法提高VIP]尤拉函式演算法函式
- [藍橋杯][演算法提高VIP]超級瑪麗演算法
- [藍橋杯][演算法提高VIP]大數加法演算法
- [藍橋杯][演算法提高VIP]奪寶奇兵 dp演算法
- 藍橋杯 -- 演算法提高 身份證號碼升級演算法
- [藍橋杯][演算法提高VIP]分蘋果 線段樹演算法蘋果
- 藍橋杯 演算法提高 拿糖果(完全揹包dp)演算法
- Java實現 藍橋杯 演算法提高 八數碼(BFS)Java演算法
- POJ 2251-Dungeon Master(BFS-三維迷宮)AST
- 藍橋杯-移動距離(最簡單的寫法)
- 藍橋杯—演算法訓練演算法
- 藍橋杯--演算法訓練演算法
- 題目 1501: [藍橋杯][演算法提高VIP]分蘋果演算法蘋果
- 藍橋杯學習路線
- 藍橋杯-波動數列
- (Day6)演算法復健運動for藍橋杯-常用數學演算法
- 藍橋杯 排序排序
- [藍橋杯][演算法提高VIP]最大乘積 貪心 雙指標演算法指標
- [Java] 藍橋杯ADV-203 演算法提高 8皇后·改Java演算法
- 藍橋杯 演算法提高 P0102(Java解題)演算法Java
- 藍橋杯_演算法提高_身份證升級(簡單字元處理)演算法字元
- 藍橋杯大賽——驅動程式
- [Java] 藍橋杯ADV-213 演算法提高 3-2求存款Java演算法
- 2016藍橋杯演算法提高——身份證號碼升級演算法
- 每天一道藍橋杯 Day3 移動字母
- 藍橋杯-N皇后
- 藍橋杯真題
- 基因牛(藍橋杯)動態規劃動態規劃
- 藍橋杯 2014屆真題 地宮取寶 動態規劃解法動態規劃
- [Java] 藍橋杯ADV-185 演算法提高 五次方數Java演算法
- 藍橋杯——查詢的妙趣