IDEA偵錯程式的使用
阿新 • • 發佈:2020-12-09
技術標籤:動態規劃演算法
題目描述
棋盤上AA點有一個過河卒,需要走到目標BB點。卒行走的規則:可以向下、或者向右。同時在棋盤上CC點有一個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因此稱之為“馬攔過河卒”。
棋盤用座標表示,AA點(0, 0)(0,0)、BB點(n, m)(n,m),同樣馬的位置座標是需要給出的。
現在要求你計算出卒從AA點能夠到達BB點的路徑的條數,假設馬的位置是固定不動的,並不是卒走一步馬走一步。
輸入格式
一行四個正整數,分別表示BB點座標和馬的座標。
輸出格式
一個整數,表示所有的路徑條數。
輸入輸出樣例
輸入 #1複製
6 6 3 3
輸出 #1
6
說明/提示
對於100 \%100%的資料,1 \le n, m \le 201≤n,m≤20,0 \le0≤馬的座標\le 20≤20。
思路:
法一:二維陣列
不能走馬所在位置及其控制點,可以用一個數組來記錄不能走的點。
狀態 dp[i][j]: 從(0,0)走到(i,j)的線路數。
轉移方程:dp[i][j]=dp[i-1][j]+dp[i][j-1];
邊界值 dp[0][0]=1;
非控制點正常轉移,控制點值都是0。
#include <bits/stdc++.h> using namespace std; int x[9]={1,1,-1,-1,2,2,-2,-2}; int y[9]={2,-2,2,-2,1,-1,1,-1}; long long a[30][30],dp[30][30]; int main() { int m,n,x2,y2; cin>>n>>m>>x2>>y2; for(int i=0; i<9; i++){//標記控制點 int xx=x2+x[i]; int yy=y2+y[i]; if(xx>=0&&yy>=0&&xx<=n&&yy<=m){ a[xx][yy]=1; } } dp[0][0]=1;//邊界 for(int i=0; i<=n; i++){ for(int j=0; j<=m; j++){ if(a[i][j]==0){ if(i>0){ dp[i][j]+=dp[i-1][j]; } if(j>0) dp[i][j]+=dp[i][j-1]; } } } cout<<dp[n][m]<<endl; return 0; }
法二:壓縮陣列變 一維
由狀態轉移方程:dp[i][j]=dp[i-1][j]+dp[i][j-1];
紅色是已經存的資料,藍色是當前待求數,更新的時候只需要 紅色的j+紅色的j-1=現在的j,行從上到下不斷更新,因此一維陣列就可以了。dp[j]=dp[j]+dp[j-1];
還需要注意的是每行的第一列,假如前面一行的第一列不可達(0),那麼當前座標就不可達(為0)有dp[0]=dp[0] *!a[i][0](上一行的j)
#include <bits/stdc++.h> using namespace std; int x[9]={1,1,-1,-1,2,2,-2,-2}; int y[9]={2,-2,2,-2,1,-1,1,-1}; long long a[30][30],dp[30]; int main() { int m,n,x2,y2,j; cin>>n>>m>>x2>>y2; for(int i=0; i<9; i++){ int xx=x2+x[i]; int yy=y2+y[i]; if(xx>=0&&yy>=0&&xx<=n&&yy<=m){ a[xx][yy]=1; } } dp[0]=1; for(int i=0; i<=n; i++){ for(dp[0]*=!a[i][0],j=1; j<=m; j++){ dp[j]+=dp[j-1]; dp[j]*= !a[i][j];//非控制點是0 } } cout<<dp[m]<<endl; return 0; }