過河卒 題目

2021-10-07 21:28:29 字數 4085 閱讀 9289

題目描述

棋盤上 a 點有乙個過河卒,需要走到目標 b 點。卒行走的規則:可以向下、或者向右。同時在棋盤上 c 點有乙個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因此稱之為「馬攔過河卒」。

棋盤用座標表示,a點 (0, 0)、b點 (n, m),同樣馬的位置座標是需要給出的。

現在要求你計算出卒從 a 點能夠到達 b 點的路徑的條數,假設馬的位置是固定不動的,並不是卒走一步馬走一步。

輸入格式

一行四個正整數,分別表示 b 點座標和馬的座標。

輸出格式

乙個整數,表示所有的路徑條數。

輸入輸出樣例

輸入6 6 3 3輸出6

說明/提示

對於 100 % 的資料,1<=n,m<=20,0<=馬的座標<=20.

分析一下

第一種想法,這道題剛入手的時候,想到的是通過查詢,由於資料較小,可以將所有的點通過二維陣列表示出來,能夠通過的點就賦值為1,不能通過的點就賦值為0。但是仔細想過後,發現不能夠解決問題,當面臨著可以向下走,也可以向左走的時候,該如何選擇?就算選擇了其中一種路徑,可是繼續走下去後,假如到達目標點或者遇到了死胡同,不能繼續往前走了,又該如何返回並嘗試另一種路徑呢?

以上問題讓我當時否定了我的這種想法,也許以後能夠有辦法解決,但是目前這個問題我一點思路還都沒有。

第二種想法,我想到由乙個點在座標軸中到達另乙個點的路徑有多少種的問題,我在高中曾經遇到過這種數學題,也就是排列組合c(n,m),這個想法給我提供了另一種思路,假如說從點(0,0)到達點(3,4)的話,路徑一共有c(7,3)或c(7,4)種。也許能夠通過這個辦法解決這個問題。可以先計算出由點(0,0)到(n,m)的總路徑數,然後減去那些經過了馬的控制點的路徑,這個計算可以通過由點(0,0)到馬的控制點的路徑數 乘以 該控制點到目標點的路徑數,但是減去的過程中,還會減去經過兩個馬的控制點的路徑數(那些重複的部分)。這樣下來,計算量會非常的大,而且很容易就多減去了,這種方法可能在最後我抽絲剝繭後會得出來正確結果,但是這種複雜程度,太容易錯誤。

重點來啦

最後我在洛谷上看了大神的題解,了解到一種方法:假設到達點(i,j)的路徑數為f[i][j]條,那麼f[i][j]=f[i-1][j]+f[i][j-1]。這個是重點,那麼就可以通過遞推來計算出到達那個點的路徑。

上**

#include

using

namespace std;

//20-7-8改 下面被注釋掉的部分是昨天7-7寫的,可惜寫了半天,還是沒寫出來,於是今天去落谷上看題解了,有了一些思路,再來。

intmain()

;int g[25]

[25]=

; cin>>n>>m>>x>>y;

//防止越界

if(x<=

18&& y<=19)

g[x+2]

[y+1]=

1;if(x<=

19&& y<=18)

g[x+1]

[y+2]=

1;if(x>=

1&& y<=18)

g[x-1]

[y+2]=

1;if(x>=

2&& y<=19)

g[x-2]

[y+1]=

1;if(x>=

2&& y>=1)

g[x-2]

[y-1]=

1;if(x>=

1&& y>=2)

g[x-1]

[y-2]=

1;if(x<=

19&& y>=2)

g[x+1]

[y-2]=

1;if(x<=

18&& y>=1)

g[x+2]

[y-1]=

1;g[x]

[y]=1;

//遞推實現

for(i=

0;i<=n;i++

)for

(j=0

;j<=m;j++)if

(!g[i]

[j])

//不為馬的控制點時

cout<

[m]<

return0;

}//下面這部分是我第二種思路,可惜最後失敗了。

//#include

//using namespace std;

//int cou(int x,int y)

//// int i,j,sum1=1,sum2=1,n,sum;

// n=x+y;

// for(i=n,j=1;j<=x;i--,j++)

// // for(i=1;i<=x;i++)

// // sum=sum1/sum2;

// return sum;

//}//int main()

//// a[0]=cou(x-1,y+2)*cou(n-x-1,m-y-2);

// a[1]=cou(x-2,y+1)*2*cou(n-x+1,m-y-2);

// a[2]=cou(x-2,y-1)*cou(1,3)*cou(n-x+1,m-y-2);

// a[3]=cou(x-1,y-2)*cou(n-x+1,m-y-2);

// a[4]=cou(x-2,y+1)*cou(3,1)*cou(n-x-1,m-y-2);

// a[5]=cou(x-2,y-1)*cou(3,3)*cou(n-x-1,m-y-2);

// a[6]=cou(x-1,y-2)*cou(2,4)*cou(n-x-1,m-y-2);

// a[7]=cou(x+1,y-2)*cou(n-x-1,m-y-2);

// a[8]=cou(x-2,y+1)*cou(n-x-2,m-y-1);

// a[9]=cou(x-2,y-1)*cou(4,2)*cou(n-x-2,m-y-1);

// a[10]=cou(x-1,y-2)*cou(3,3)*cou(n-x-2,m-y-1);

// a[11]=cou(x+1,y-2)*cou(1,3)*cou(n-x-2,m-y-1);

// a[12]=cou(x+2,y-1)*cou(n-x-2,m-y-1);

// a[13]=cou(x-2,y-1)*cou(n-x+2,m-y-1);

// a[14]=cou(x-2,y-1)*cou(n-x-2,m-y+1);

// a[15]=cou(x-1,y-2)*cou(n-x-1,m-y+2);

// a[16]=cou(x+1,y-2)*cou(n-x-2,m-y+1);

// a[17]=cou(x-2,y+1)*2*cou(n-x-1,m-y-2);

// a[18]=cou(x-2,y-1)*cou(1,2)*cou(n-x-1,m-y-2);

// a[19]=cou(x-1,y-2)*cou(n-x-1,m-y-2);

// a[20]=cou(x-2,y-1)*2*cou(n-x+1,m-y-2);

// a[21]=cou(x-1,y-2)*cou(n-x-1,m-y-2);

// a[22]=cou(x-2,y-1)*cou(n-x-2,m-y-1);

// a[23]=cou(x-1,y-2)*cou(n-x-2,m-y-1);

// a[24]=cou(x-1,y-2)*cou(3,1)*cou(n-x-2,m-y-1);

// a[25]=cou(x+1,y-2)*2*cou(n-x-2,m-y-1);

// a[26]=cou(x-2,y-1)*cou(n-x-2,m-y-1);

// a[27]=cou(x-1,y-2)*2*cou(n-x-2,m-y+1);

// for(i=0;i<28;i++)

// // cout/}

第一次寫,: ) 有點亂,以後盡量改一下。

再來個大神題解鏈結吧

新增鏈結描述

過河卒演算法

過河卒基本思想 利用動態規劃轉空間為時間,利用動態規劃一般方法,把資料記錄下來,同時走兩條路線,只要不重合就好 include include include include define maxx a,b,c,d max max a,b max c,d using namespace std in...

過河卒 遞推

description 如圖,a 點有乙個過河卒,需要走到目標 b 點。卒行走規則 可以向下 或者向右。同時在棋盤上的任一點有乙個對方的馬 如上圖的c點 該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。例如上圖 c 點上的馬可以控制 9 個點 圖中的p1,p2 p8 和 c 卒不能通過對方馬的...

過河卒 題解

以前碼的 include include using namespace std long long b 21 21 int n,m,a,b void init if a 2 0 b 1 0 把馬的位置和所有馬能走到的位置都賦為0,注意考慮邊界 b a 2 b 1 0 if a 2 0 b 1 m ...