1. 程式人生 > >1647: 穿越雷區

1647: 穿越雷區

次數 cnblogs 循環 ++ oid 決賽 stream n) 表示

題目描述

X星的坦克戰車很奇怪,它必須交替地穿越正能量輻射區和負能量輻射區才能保持正常運轉,否則將報廢。
某坦克需要從A區到B區去(A,B區本身是安全區,沒有正能量或負能量特征),怎樣走才能路徑最短? 已知的地圖是一個方陣,上面用字母標出了A,B區,其它區都標了正號或負號分別表示正負能量輻射區。
例如:
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + - 坦克車只能水平或垂直方向上移動到相鄰的區。

輸入

輸入第一行是一個整數n,表示方陣的大小, 4<=n<100
接下來是n行,每行有n個數據,可能是A,B,+,-中的某一個,中間用空格分開。
A,B都只出現一次。

輸出

要求輸出一個整數,表示坦克從A區到B區的最少移動步數。
如果沒有方案,則輸出-1

樣例輸入

5
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + -

樣例輸出

10

提示

來源

藍橋杯2015年決賽

conclude:

1.兩個回溯(標記需要“切記:不能走原路,否則死循環”,遞歸for循環分類需要);

2.找最小問題用技巧減少遞歸次數;

3.讀取空格隔開的字符不能用scanf;

#include <iostream>
#include <cstring>
using namespace std;
int mi=1000; char map[100][100]; int mark[100][100]={0}; int x,y,n; int x0,y0; int a[4]={0,0,1,-1}; //這樣下標就從0開始了。 int b[4]={1,-1,0,0}; void dfs(int k) { if(x<1||y<1||x>n||y>n) //出界遞歸結束 { return; } if(k>mi) // !!!關鍵所在!!! return
; //找最小,超過最小就不用找了,遞歸結束 if(map[x][y]==B) { mi=k; return; //找到了也要結束遞歸 } mark[x][y]=1; for(int i=0;i<=3;i++) { if(map[x+a[i]][y+b[i]]!=map[x][y]&&!mark[x+a[i]][y+b[i]]) { x+=a[i]; y+=b[i]; dfs(k+1); x-=a[i]; //循環內部回溯 y-=b[i]; } } mark[x][y]=0; //標記,不能走原路!!!!!循環外部也不要回溯 !!! } int main() { cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>map[i][j]; //!!!!不能用scanf%c,他可以讀取空格。 if(map[i][j]==A) { x=i; y=j; } } } dfs(0); if(mi==1000) cout<<-1; else cout<<mi; }

1647: 穿越雷區