【8月刷题打卡】路径计数2

207 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

路径计数2

题目描述

一个N×NN \times N的网格,你一开始在(1,1)(1,1),即左上角。每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N,N)(N,N),即右下角有多少种方法。

但是这个问题太简单了,所以现在有MM个格子上有障碍,即不能走到这MM个格子上。

输入格式

输入文件第11行包含两个非负整数N,MN,M,表示了网格的边长与障碍数。

接下来MM行,每行两个不大于NN的正整数x,yx, y。表示坐标(x,y)(x, y)上有障碍不能通过,且有1x,yn1≤x, y≤n,且x,yx, y至少有一个大于11,并请注意障碍坐标有可能相同。

输出格式

一个非负整数,为答案mod100003 \bmod 100003后的结果。

样例 #1

样例输入 #1

3 1
3 1

样例输出 #1

5

提示

对于20%20\%的数据,有N3N≤3

对于40%40\%的数据,有N100N≤100

对于40%40\%的数据,有M=0M=0

对于100%100\%的数据,有N1000,M100000N≤1000,M≤100000

首先,题目描述的重点在于每次只能移动到下方相邻的格子或者右方相邻的格子,所以,我们就可以得出结论:到达第n个格子的路径数量是这个格子左边的格子的路径数量+上边格子的路径数量。我们定义一个DP数组,DP[i][j](也就是状态)代表第M[i][j]个格子的路径数量,根据上面的推论,我们可以得出状态转移方程:DP[i][j] = DP[i-1][j]+DP[i][j-1];

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>

using namespace std;

int n,m,g[1001][1001];
bool v[1001][1001];		//判断是否有障碍 

int main()
{
	int x,y;
	memset(g,0,sizeof g);	//初始化步数都为0 
	memset(v,0,sizeof v);	//路障都为0 
	scanf("%d%d",&n,&m);
	
	for(int i=1;i<=m;i++) {
		scanf("%d%d",&x,&y);
		v[x][y]=1;
	}
	
	g[0][1]=1;		//初始化第一步棋子 
	
	for(int i=1;i<=n;i++)//逐步开始递推
		for(int j=1;j<=n;j++) {
			g[i][j]=(g[i-1][j]+g[i][j-1])%100003;	//一定要取模 
			if(v[i][j]==1)//这个地方是障碍,那么到这里的步数都为0 
				g[i][j]=0;
		}
	printf("%d",g[n][n]);//最后终点的部署及为答案。 
	return 0;//结束 
}