NYOJ 58 最少步數
阿新 • • 發佈:2019-01-26
(一)深搜法:
1.遞迴的邊界:
走到終點座標, 即(x == x2 && y == y2);
2.遞迴進行的條件:
for迴圈的 4個方向(定義了一個方向陣列move)進行遞迴:
判斷條件:若為路 && 未標記 && 不越界, 則繼續遞迴;即(A[x][y] == 0 && flag[x][y] == 0 && x >= 0 && x <= 8 && y >= 0 && y <= 8)
在走的過程中,要注意標記和清除走過的點,還原走過的位置。
程式碼1:
程式碼2:#include<stdio.h> #include<stdlib.h> #include<string.h> int A[9][9] = { 1,1,1,1,1,1,1,1,1, 1,0,0,1,0,0,1,0,1, 1,0,0,1,1,0,0,0,1, 1,0,1,0,1,1,0,1,1, 1,0,0,0,0,1,0,0,1, 1,1,0,1,0,1,0,0,1, 1,1,0,1,0,1,0,0,1, 1,1,0,1,0,0,0,0,1, 1,1,1,1,1,1,1,1,1}; int flag[9][9];//flag標記陣列; int min = 0x7FFFFFFF, sum1 = 0; typedef struct item { int x; int y; }dir; dir move[4] = {1, 0, 0, -1, -1, 0, 0, 1};//方向陣列; void walking(int x, int y, int x2, int y2,int sum); int main(void) { int N; scanf("%d", &N); while(N--) { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); walking(x1, y1, x2, y2,0); printf("min = %d\n", min); //sum = 0; min = 0x7FFFFFFF; memset(flag, 0, sizeof(flag)); } return 0; } void walking(int x, int y, int x2, int y2,int sum)//(x,y)當前座標,(x2, y2)終點座標 { int i; if(x == x2 && y == y2)//遞迴結束; { if(sum < min) min = sum; return ; } // if(0 <= x || x >= 8 || 0 <= y || y >= 8)//已經走過 or 越界; // return ; for(i = 0; i < 4; i++) { x = x + move[i].x; y = y + move[i].y; if(x >= 0 && x <= 8 && y >= 0 && y <= 8 && A[x][y] == 0 && flag[x][y] == 0)//若為路,繼續遞迴; { flag[x][y] = 1; //sum++; walking(x, y, x2, y2,sum + 1); flag[x][y] = 0; x = x - move[i].x; y = y - move[i].y; // sum--; } }//for }
程式碼3(最優):#include<stdio.h> #include<stdlib.h> #include<string.h> int A[9][9] = {//0路1牆; 1,1,1,1,1,1,1,1,1, 1,0,0,1,0,0,1,0,1, 1,0,0,1,1,0,0,0,1, 1,0,1,0,1,1,0,1,1, 1,0,0,0,0,1,0,0,1, 1,1,0,1,0,1,0,0,1, 1,1,0,1,0,1,0,0,1, 1,1,0,1,0,0,0,0,1, 1,1,1,1,1,1,1,1,1}; int flag[9][9];//flag標記陣列; int min,x2, y2;//將終點定義為全域性變數; typedef struct item { int x; int y; }dir; dir move[4] = {1, 0, 0, -1, -1, 0, 0, 1};//方向陣列; void walking(int x, int y, int sum);//精簡遞迴函式,引數中和只有變化的量;sum代表當前走了多少步; int main(void) { int N; scanf("%d", &N); while(N--) { int x1, y1;//每次迴圈開始前進行初始化; min = 0x7FFFFFFF; memset(flag, 0, sizeof(flag)); scanf("%d%d%d%d", &x1, &y1, &x2, &y2); walking(x1, y1, 0); printf("%d\n", min); } return 0; } void walking(int x, int y, int sum) { int i; if(x == x2 && y == y2)//遞迴結束; { if(sum < min) min = sum; return ; } for(i = 0; i < 4; i++) { x = x + move[i].x; y = y + move[i].y; if(A[x][y] == 0 && flag[x][y] == 0 && x >= 0 && x <= 8 && y >= 0 && y <= 8)//若為路 && 未標記 && 不越界, 則繼續遞迴; { flag[x][y] = 1; walking(x, y, sum + 1); flag[x][y] = 0; } x = x - move[i].x;//*** y = y - move[i].y;//*** }//for }
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int A[9][9] = {
1,1,1,1,1,1,1,1,1,
1,0,0,1,0,0,1,0,1,
1,0,0,1,1,0,0,0,1,
1,0,1,0,1,1,0,1,1,
1,0,0,0,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,0,0,0,1,
1,1,1,1,1,1,1,1,1};
int flag[9][9];//flag標記陣列;
int min;
typedef struct item
{
int x;
int y;
}dir;
int move[8] = {1, 0, 0, -1, -1, 0, 0, 1};//方向陣列;
void walking(int x, int y, int x2, int y2,int sum);
int main(void)
{
int N;
scanf("%d", &N);
while(N--)
{
int x1, y1, x2, y2;
min = 0x7FFFFFFF;
memset(flag, 0, sizeof(flag));
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
walking(x1, y1, x2, y2,0);
printf("min = %d\n", min);
}
return 0;
}
void walking(int x, int y, int x2, int y2,int sum)//(x,y)當前座標,(x2, y2)終點座標
{
int i;
if(x == x2 && y == y2)//遞迴結束;
{
if(sum < min)
min = sum;
return ;
}
for(i = 0; i < 8; i+= 2)
{
x += move[i];
y += move[i + 1];
if(x >= 0 && x <= 8 && y >= 0 && y <= 8 && A[x][y] == 0 && flag[x][y] == 0)//若為路,繼續遞迴;
{
flag[x][y] = 1;
walking(x, y, x2, y2,sum + 1);
flag[x][y] = 0;
}
x -= move[i];
y -= move[i + 1];
}//for
}