1. 程式人生 > 實用技巧 >IDEA偵錯程式的使用

IDEA偵錯程式的使用

技術標籤:動態規劃演算法

題目描述

棋盤上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;
}