題目描述
shopee的辦公室非常大,小蝦同學的位置坐落在右上角,而大門卻在左下角,可以把所有位置抽象為一個網格(門口的坐标為0,0),小蝦同學很聰明,每次隻向上,或者向右走,因為這樣最容易接近目的地,但是小蝦同學不想讓自己的boss們看到自己經常在他們面前出沒,或者遲到被發現。他決定研究一下如果他不通過boss們的位置,他可以有多少種走法?
輸入描述:
第一行 x,y,n (0<x<=30, 0<y<=30, 0<=n<= 20) 表示x,y小蝦的座位坐标,n 表示boss的數量( n <= 20)
接下來有n行, 表示boss們的坐标(0<xi<= x, 0<yi<=y,不會和小蝦位置重合)
x1, y1
x2, y2
……
xn, yn
輸出描述:
輸出小蝦有多少種走法
示例1
輸入
3 3 2
1 1
2 2
輸出
4
題目解析
這道題是走方格的更新版,但也不過就是加了個障礙而已,難度還是很簡單的,不過,這裡使用dfs遞歸會逾時,是以隻能轉而采用動态規劃思路實作。
-
第一步:劃分子問題
求解的是到(x,y)有多少條路徑,那麼在求解過程中一定需要知道到達(i,j)(i<=x,j<=y)有多少條路經,子問題很容易找到了吧。
-
狀态轉移方程
dp【i】【j】表示的是到(i,j)這個點有多少條路徑,沒什麼好解釋的,自然而然得出該結論
dp【i+1】【j】=dp【i+1】【j】+dp【i】【j】
表示的含義是:到達(i+1,j)點數目包括從下方這個點(i,j)的所有路徑
dp【i】【j+1】=dp【i】【j+1】+dp【i】【j】
表示的含義是:到達(i,j+1)點數目包括從左方這個點(i,j)的所有路徑
-
填表
為了最大程度節省空間,我們令障礙(i,j)的dp【i】【j】=-1,那麼當求解釋,遇到障礙直接跳過
初始化:dp【i】【j】={0}
到達(0,0)點隻有一條路徑,是以dp【0】【0】=1
注意!一定令dp數組定義為long long型,因為數組幾乎成斐波那契數列這樣增長的,是以速度超快的
接下來就是代碼實作
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<utility>
#include<cmath>
#include<limits.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
ll dp[31][31];
int n;
int main() {
int x,y;
while(scanf("%d%d%d",&x,&y,&n)!=EOF){
memset(dp,0,sizeof(dp));
int xt,yt;
dp[0][0]=1;
while(n--){
scanf("%d%d",&xt,&yt);
dp[xt][yt]=-1;
}
dp[0][0]=1;
for(int i=0;i<=x;i++){
for(int j=0;j<=y;j++){
if(dp[i][j]==-1){
continue;
}
if(j<y&&dp[i][j+1]!=-1){
dp[i][j+1]+=dp[i][j];
}
if(i<x&&dp[i+1][j]!=-1){
dp[i+1][j]+=dp[i][j];
}
}
}
printf("%lld\n",dp[x][y]);
}
return 0;
}