深搜递归回来时候,取消与不取消标记的探讨
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <stdlib.h> 6 #include <vector> 7 #include <map> 8 #include <queue> 9 #include <string> 10 #include <iostream> 11 #include <ctype.h> 12 #include <string.h> 13 #include <set> 14 #include <stack> 15 #include<functional> 16 using namespace std; 17 #define Size 22 18 #define maxn 1<<30 19 #define minn 1e-6 20 char a[Size][Size]; 21 int mark[Size][Size]; 22 int stx, sty; 23 int width, len; 24 int ans; 25 int go[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 }; 26 void solve(int x,int y,int step){ 27 if (x<1 || y<1 || x>len || y>width||a[x][y]=='#'){ 28 if (ans < step){ 29 cout << step << endl; 30 ans = step; 31 } 32 } 33 else { 34 for (int i = 0; i < 4; i++){ 35 int tx = x + go[i][0]; 36 int ty = y + go[i][1]; 37 if (mark[tx][ty]) continue; 38 if (a[tx][ty] == '.') step++; 39 mark[tx][ty] = 1; 40 solve(tx, ty,step); 41 mark[tx][ty] = 0;//所以不标记的情况一般是在重复使用字母,数字的时候,解空间很小的情况下,如果要搜索地图的时候,不标记,时间太多不可接受 42 /* 43 虽然可能搜索到最终答案但是,解空间是非常大的如果不标记的话那么,因为除过此来到的路其他路都要再走一次,解空间非常大非常大可能是3^64 44 因为其等于计算了从起点到地图上任意一点的所有路径,假设每次有三个选择,那么在一个8*8的地图上那么总共要计算的次数是64*3^64,天文数字 而不取消标记的情况是计算,即深搜的模板方案,是计算最佳方案的即为,计算最快到达i,j点的路径,要计算最慢到达ij的路径就不行了,此题等效计算最长路径 45 */ 46 if (a[tx][ty] == '.') step--; 47 } 48 } 49 } 50 51 int main(){ 52 53 while (cin >> width >> len){ 54 int num = 0; 55 for (int i = 1; i <= len; i++) 56 for (int j = 1; j <= width; j++){ 57 mark[i][j] = 0; 58 cin >> a[i][j]; 59 if (a[i][j] == '@') stx = i, sty = j; 60 } 61 mark[stx][sty] = 1; 62 ans = 0; 63 solve(stx, sty,1);//将要探索stx,sty,以及走了0步了 64 } 65 return 0; 66 }
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <stdlib.h> 6 #include <vector> 7 #include <map> 8 #include <queue> 9 #include <string> 10 #include <iostream> 11 #include <ctype.h> 12 #include <string.h> 13 #include <set> 14 #include <stack> 15 #include<functional> 16 using namespace std; 17 #define Size 78 18 #define maxn 1<<30 19 #define minn 1e-6 20 char a[Size][Size]; 21 int mark[Size][Size]; 22 int width, len; 23 int stx, sty, edx, edy; 24 int ans; 25 /* 26 当x2,y2在x1,y1的左上角时,他首选的路线是上和左,其次才是右和下;其它方向同理 27 mark 标记 28 递归 29 mark 标记去除 30 31 这种递归的找所有解的方案,方向的选取就起着决定性的作用 32 33 int go[4][2] = { { 0, -1 }, { 0, 1 }, { 1, 0 }, { -1, 0 } }; 超时 34 int go[4][2]={{0,1},{1,0},{0,-1},{-1,0}};就过了 35 */ 36 int go[4][2] = { { 0, -1 }, { 0, 1 }, { 1, 0 }, { -1, 0 } }; 37 void solve(int x, int y, int step, int direction){ 38 if (step > ans) return; 39 if (x == edx&&y == edy){ 40 ans = step; 41 return; 42 } 43 for (int i = 0; i < 4; i++){ 44 int tx = x + go[i][0]; 45 int ty = y + go[i][1]; 46 if (tx<0 || ty<0 || tx>len+1 || ty>width+1) continue; 47 if (mark[tx][ty] == 1) continue; 48 if (a[tx][ty] == ' ' || a[tx][ty] == 'X'&&tx == edx&ty == edy){ 49 mark[tx][ty] = 1; 50 if (direction == i) solve(tx, ty, step, i); 51 else solve(tx, ty, step + 1, i); 52 mark[tx][ty] = 0; 53 } 54 } 55 } 56 int main(){ 57 int b = 1; 58 while (scanf("%d%d",&width,&len)==2){ 59 if (width == 0&&len==0) break; 60 for (int i = 0; i<77; i++) 61 a[i][0] = a[0][i] = ' '; 62 for (int i = 1; i<len + 1; i++){ 63 getchar(); 64 for (int j = 1; j<width + 1; j++) 65 a[i][j] = getchar(); 66 } 67 for (int i = 0; i<width + 1; i++) 68 a[len + 1][i + 1] = ' '; 69 for (int i = 0; i<len + 1; i++) 70 a[i + 1][width + 1] = ' '; 71 72 int Case = 1; 73 printf("Board #%d:\n", b++); 74 while (scanf("%d%d%d%d",&sty,&stx,&edy,&edx)==4){ 75 if (sty == 0) break; 76 memset(mark, 0, sizeof(mark)); 77 ans = 9999; 78 solve(stx, sty, 0, -1); 79 if (ans == 9999) printf("Pair %d: impossible.\n", Case); 80 else 81 printf("Pair %d: %d segments.\n", Case, ans); 82 Case++; 83 } 84 cout << endl; 85 } 86 return 0; 87 }