題目鏈接:https://www.luogu.org/problem/P1605
題目背景:
給定一個N*M方格的迷宮,迷宮裏有T處障礙,障礙處不可通過。給定起點座標和終點座標,問: 每個方格最多經過1次,有多少種從起點座標到終點座標的方案。在迷宮中移動有上下左右四種方式,每次只能移動一個方格。數據保證起點上沒有障礙。
輸入格式:
第一行N、M和T,N爲行,M爲列,T爲障礙總數。第二行起點座標SX,SY,終點座標FX,FY。接下來T行,每行爲障礙點的座標。
輸出格式:
給定起點座標和終點座標,問每個方格最多經過1次,從起點座標到終點座標的方案總數。
輸入輸出樣例
輸入 #1
2 2 1
1 1 2 2
1 2
輸出 #1
1
說明/提示
【數據規模】
1≤N,M≤5
分析:此題採用回溯的思想
1. 回溯算法概念:
回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。
回溯法是一種選優搜索法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。
許多複雜的,規模較大的問題都可以使用回溯法,有“通用解題方法”的美稱。
2. 回溯法的基本思想
在包含問題的所有解的解空間樹中,按照深度優先搜索的策略,從根結點出發深度探索解空間樹。當探索到某一結點時,要先判斷該結點是否包含問題的解,如果包含,就從該結點出發繼續探索下去,如果該結點不包含問題的解,則逐層向其祖先結點回溯。(其實回溯法就是對隱式圖的深度優先搜索算法)。
若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜索遍才結束。
3. 回溯法遞歸框架
回溯法是對解空間的深度優先搜索,在一般情況下使用遞歸函數來實現回溯法比較簡單,其中i爲搜索的深度,框架如下:
1: int a[n];
2: try(int i)
3: {
4: if(i>n)
5: 輸出結果;
6: else
7: {
8: for(j = 下界; j <= 上界; j=j+1) // 枚舉i所有可能的路徑
9: {
10: if(fun(j)) // 滿足限界函數和約束條件
11: {
12: a[i] = j;
13: ... // 其他操作
14: try(i+1);
15: 回溯前的清理工作(如a[i]置空值等);
16: }
17: }
18: }
19: }
c++代碼實現:
#include <iostream>
using namespace std;
int pic[6][6];
int dx[4] = {0, 0, -1, 1};
int dy[4]= {-1, 1, 0, 0};
int ans = 0; //計算總的路徑數
int N,M,T;
int SX, SY;
int FX, FY;
int temp[6][6];
void dfs(int x,int y)
{
if(x==FX && y == FY)
{
ans++;
return;
}
else
{
for(int i=0;i<4;i++)
{
if(temp[x+dx[i]][y+dy[i]] == 0 && pic[x+dx[i]][y+dy[i]]==1)
{
temp[x][y] = 1;
dfs(x+dx[i], y+dy[i]);
temp[x][y] = 0;
}
}
}
}
int main()
{
cin>>N>>M>>T;
for(int i=1;i<=N;i++)
{
for (int j = 1; j <= M; j++)
{
pic[i][j] = 1;
}
}
cin>>SX>>SY;
cin>>FX>>FY;
for(int i=0;i<T;i++)
{
int t1,t2;
cin>>t1>>t2;
pic[t1][t2] = 0;
}
dfs(SX, SY);
cout<<ans<<endl;
return 0;
}
python3代碼實現:
# dx = [0, 1, 0, -1]
# dy = [1, 0, -1, 0]
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
INIT_ROW = 100
INIT_COL = 100
def walk(x, y):
global count
if x == EX and y == EY:
count += 1
return
else:
for i in range(4):
if temp[x + dx[i]][y + dy[i]] == 0 and pic[x + dx[i]][y + dy[i]] == 1:
temp[x][y] = 1
walk(x + dx[i], y + dy[i])
temp[x][y] = 0
if __name__ == '__main__':
s1 = list(map(int, input().split(' ')))
N, M, T = s1[0], s1[1], s1[2]
s2 = list(map(int, input().split(' ')))
SX, SY, EX, EY = s2[0], s2[1], s2[2], s2[3]
pic = []
temp = []
for i in range(INIT_ROW):
pic.append([0 for i in range(INIT_ROW)])
temp.append([0 for i in range(INIT_COL)])
for i in range(1, N+1):
for j in range(1, M+1):
pic[i][j] = 1
for k in range(T):
row = list(map(int, input().split(' ')))
pic[row[0]][row[1]] = 0
print(pic)
print(temp)
count = 0
walk(SX, SY)
print(count)