題目描述
棋盤上 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 ...