【遞推】過河卒
阿新 • • 發佈:2019-02-09
【題目描述】
如圖,A 點有一個過河卒,需要走到目標 B 點。卒行走規則:可以向下、或者向右。同時在棋盤上的任一點有一個對方的馬(如上圖的C點),該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。例如上圖 C 點上的馬可以控制 9 個點(圖中的P1,P2 … P8 和 C)。卒不能通過對方馬的控制點。
【輸入】
鍵盤輸入
B點的座標(n,m)以及對方馬的座標(X,Y){不用判錯}
【輸出】
螢幕輸出
一個整數(路徑的條數)。
【樣例輸入】
6 6 3 2
【樣例輸出】
17
【AC程式碼】
#include<iostream> #include<cstdio> //用scanf(),printf()輸入輸出加快速度 #include<cstring> //cstring內有memset()函式 using namespace std; int a[9]={0,-1,-1,-2,-2,1,1,2,2}; //陣列a[]儲存馬控制的橫座標範圍 int b[9]={0,2,-2,1,-1,2,-2,1,-1}; //陣列b[]儲存馬控制的縱座標範圍,注意相同下標的a,b之間有一定的對應關係,即除了(0,0)外|a|與|b|一個為1,另一個為2 int n,m,x,y,i,j; int map[21][21]; //map[i][j]表示地圖上(i,j)這個點是否是馬的控制點 long long tripnum[21][21]; //tripnum[i][j]表示從(0,0)到(i,j)卒合法的行走路線總數 int main() { memset(tripnum,0,sizeof(tripnum)); scanf("%d%d%d%d",&n,&m,&x,&y); for(i=0;i<=20;i++) for(j=0;j<=20;j++) map[i][j]=1; //map[i][j]為1時表示(i,j)非控制點 for(i=0;i<=8;i++) if(x+a[i]<=20 && x+a[i]>=0 && y+b[i]<=20 && y+b[i]>=0) //如果控制點在地圖範圍內,即這個點存在 map[x+a[i]][y+b[i]]=0; //將其設為0,表示這裡被馬控制 for(j=0;j<=20;j++) //從左到右遍歷最上面一行的所有點 if(map[0][j]==1) //如果這個點不是控制點 tripnum[0][j]=1; //那麼從(0,0)到達這個點的路線自然只有一條 else //否則這點不可到達,路線數為初值0條 break; //並且其右的點也不可達,不必繼續遍歷 for(i=0;i<=20;i++) //從上到下遍歷最左邊一列的所有點 if(map[i][0]==1) //如果這個點不是控制點 tripnum[i][0]=1; //那麼從(0,0)到達這個點的路線自然只有一條 else //否則這點不可到達,路線數為初值0條 break; //並且其下的點也不可達,不必繼續遍歷 for(i=1;i<=n;i++) //從(1,1)這個點開始,逐行的去看(也可以逐列) for(j=1;j<=m;j++) if(map[i][j]==1) //如果這個點不是控制點 tripnum[i][j]=tripnum[i-1][j]*map[i-1][j]+tripnum[i][j-1]*map[i][j-1]; //那麼到達它的路線數等於其左的點路線與其上的點之和,由於其左與其上的點有可能是控制點,所以要乘以控制係數map[i][j](這也是為什麼用0代表控制,而用1代表非控制,而不是調換過來的原因) printf("%lld",tripnum[n][m]); return 0; }