走格子/棋盤問題 有多少條路徑可走
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
選擇題:在如下8*6的矩陣中,請計算從A移動到B一共有多少走法?要求每次只能向上或向右移動一格,並且不能經過P。()
B | |||||||
P | |||||||
A |
A 492 B 494 C 496 D 498
看一次忘一次,決定這次再次理解一便,並更加形象的理解:
試想:
題目若是m*n表格裡面,從A到B,不管其如何走,必然要經過m+n個格子(這個就不需要證明了吧)。然後這m+n個格子裡面只有兩種狀態,向上或向右;而且為到達B,必須有n個向右走,m個向上走;如此,從這m+n個格子裡選擇n個向右走就ok了(剩下的就向上走,當然可以選擇m向上走,剩下向右走)。這樣可能會比原解釋的要更加清楚些~
其他的,參考原解釋:
附原解釋:
解答:
這是有關組合數學中排列組合的一道題。
從n個元素中任取r個元素一組,若不考慮它們的順序時,則稱為從n中取r的組合,它的方案數以C(n,r) 表示;
從n個元素中任取r個元素按順序排成一列,則稱為從n中取r的排列,其排列的方案數以p(n,r) 表示。
這道題等同於下面的一道題:
許多街道都建成方格形。從家中出發到目的地,向東要走m條街,想北要走n條街,試問從家中到工作地點最短路徑有幾條?
若將家作為 (0,0)點,工作地點作為(m,n)點,問題就化為從(0,0)點到(m,n)點有幾條最短路徑(如下圖)
從(0,0)點到(m,n)點走的路徑,必然是向x軸方向過m次街道,y軸方道路向過n個街道。即每條道路和由m個x和n個y構成的共m+n的排列一一對應,可以看成在m+n個格中
選m個格子,填上x,剩下的n個格子填上y,這樣的排列數為c(m+n,m),同理,這樣的排列數為c(m+n,n)。
現在我們來解決拿到面試題:
每個方格看做一個點,得到下面座標圖:
首先從A到B總共有c(7+5,5)種走法,從A到P有c(3+3,3)種走法,從P到B有c(4+2,2)種走法。
所以不經過點P得走法共有c(12,5)-(c(6,3)*c(6,2))種,即492種,選A。
給定一個m*n的格子或棋盤,問從左下角走到右上角的走法總數(每次只能向右或向上移動一個方格邊長的距離)。
解答:我們可以把棋盤的左下角看做二維座標的原點(0,0),把棋盤的右上角看做二維座標(n,n)(座標系的單位長度為小方格的變長)用f(i,j)表示移動到座標f(i,j)的走法總數,其中0=<i,j<=n,我們即求f(n,n)這樣我們就可以遞迴的定義子問題
f(n,n)=f(n-1,n)+f(n,n-1).
於是狀態f(i,j)的狀態轉移方程為:
f(i,j)=f(i-1,j)+f(i,j-1) if i,j>0
f(i,j)=f(i,j-1) if i=0
f(i,j)=f(i-1,j) if j=0
初始情況就為:f(0,0)=0, f(0,1)=1, f(1,0)=1,這個問題可以在時間O(n^2),空間O(n^2)內求解,非遞迴解。
1,給定一個n*n的格子或棋盤,問從左下角走到右上角的走法總數(每次只能向右或向上移動一個方格邊長的距離) 解答:我們可以把棋盤的左下角看做二維座標的原點(0,0),把棋盤的右上角看做二維座標(n,n)(座標系的單位長度為小方格的變長)
f(n,n)=f(n-1,n)+f(n,n-1). 於是狀態f(i,j)的狀態轉移方程為: f(i,j)=f(i-1,j)+f(i,j-1) if i,j>0 f(i,j)=f(i,j-1) if i=0 f(i,j)=f(i-1,j) if j=0 初始情況就為:f(0,0)=0, f(0,1)=1, f(1,0)=1,這個問題可以在時間O(n^2),空間O(n^2)內求解,非遞迴解。
2,給定一個m*n的格子或棋盤,問從左下角走到右上角的走法總數(每次只能向右或向上移動一個方格邊長的距離) 解答:這個問題和第1題的解答是類似的。只不過最終求的是f(m,n)=f(m-1,n)+f(m,n-1),初始為f(0,0)=0,f(0,1)=1,f(1,0)=1,所以兩個解法的通用方案為: /* 走方格問題,給定一個m*n的小方格子組成的棋盤,問從棋盤左下角走到右上角的走法總數。 遞迴解 */ int solve_cube_work(int m,int n){ if(m==0 && n==0) return 0; if(m==1 && n==0) return 1; if(m==0 && n==1) return 1; if(m==0) return solve_cube_work(m,n-1); if(n==0) return solve_cube_work(m-1,n); return solve_cube_work(m-1,n)+solve_cube_work(m,n-1); } /* 走方格問題,給定一個m*n的小方格子組成的棋盤,問從棋盤左下角走到右上角的走法總數。 非遞迴解 */ int solve_cube_work_iter(int m,int n){ int **Q=new int*[m+1]; for(int i=0;i<=m;i++){ Q[i]=new int[n+1](); } //初始化 Q[0][0]=0; for(int j=1;j<=n;j++) Q[0][j]=1; for(int i=1;i<=m;i++) Q[i][0]=1; //迭代計算 for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ Q[i][j]=Q[i-1][j]+Q[i][j-1]; } } int res=Q[m][n]; delete [] Q; return res; }