题意:给你一个地图,上面有一些‘X',给你起点终点,让你输出从起点到终点的路径中转向(改变方向)次数最少的路径,注意,不能穿过别的’X'并且可以超过边界
题解:关于超过边界,只要在外围多加一圈‘ ’。然后正常dfs就行。
关于转向次数的记录,每次dfs时传递上一次的方向f,然后进行判断。
技巧:if判断用几个flag来简化表达式。(t1t2t3)
坑:1.dfs的方向顺序原来不能随便打的啊。。。//要绕圈,不然会同方向来回走位,不像有vis数组的bfs。
2.getline 循环时只需要第一次getchar
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <math.h> #include <string.h> #include <string> #include <map> #include<stack> #include<set> #include<string.h> #define pb push_back #define _for(i, a, b) for (int i = (a); i<(b); ++i) #define _rep(i, a, b) for (int i = (a); i <= (b); ++i) using namespace std; const int N = 75+ 5; //double num[N], price[N], ave[N]; int board[N][N], mark[N][N]; int w, h, mn; int dir[4][2] = { 0,1 ,-1,0, 0,-1, 1,0 }; void Search(int now_x, int now_y, int end_x, int end_y, int step, int f) {//f 上一步的方向。 if (step > mn)return; if (now_x == end_x&&now_y == end_y) { if (mn > step) { mn = step; return; } } _for(i, 0, 4) { int x = now_x + dir[i][0]; int y = now_y + dir[i][1]; int t1 = 0, t2 = 0, t3 = 0; if (((x > -1 )&&( x < w + 2)) && ((y > -1) &&( y < h + 2)))t1 = 1; if ((board[y][x] == 0) && (mark[y][x] == 0))t2 = 1; if ((x == end_x)&&(y == end_y)&&board[y][x]==1) t3 = 1; if (t1 && (t2 || t3)) { mark[y][x] = 1; if (f == i) Search(x, y, end_x, end_y, step, i); else Search(x, y, end_x, end_y, step + 1, i); mark[y][x] = 0; } } } int main() { int kase = 0; while(cin >> w >> h) { memset(board, 0, sizeof(board)); memset(mark, 0, sizeof(mark)); if (w == 0 && h == 0)break; printf("Board #%d: ", ++kase); string s; getchar(); _for(i, 0, h) { getline(cin, s); _for(j, 0, w) { if (s[j] == 'X')board[i+1][j+1] = 1;//外围加一圈 } } int x, y, xx, yy,cnt=0; while (cin >> x >> y >> xx >> yy) { if (x == 0 && y == 0 && xx == 0 && yy == 0) break; mn = 100000; Search(x, y, xx, yy,0,-1); if (mn < 100000)printf("Pair %d: %d segments. ", ++cnt, mn); else printf("Pair %d: impossible. ", ++cnt); } cout << endl; } system("pause"); }