Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
一个N×N的网格,你一开始在(1, 1),即左上角。每次只能移动到下方相邻的格子或者右方相邻的格子,问到达(N, N),即右下角有多少种方法。 但是这个问题太简单了,所以现在有M个格子上有障碍,即不能走到这M个格子上。【输入格式】
输入文件path.in的第1行包含两个非负整数N,M,表示了网格的边长与障碍数。 接下来M行,每行两个不大于N的正整数x, y。表示坐标(x, y)上有障碍不能通过,且有1≤x, y≤n,且x, y至少有一个大于1,并请注意障碍坐标有可能相同。
【输出格式】
输出文件path.out仅包含一个非负整数,为答案mod 100003后的结果。
【数据规模】
对于20%的数据,有N≤3; 对于40%的数据,有N≤100; 对于40%的数据,有M=0; 对于100%的数据,有N≤1000,M≤100000。
Sample Input1
3 1 3 1
Sample Output1
5
【题解】
这题和马拦过河卒那题很像。
但是这题更好做了。不用你处理出马控制的区域。直接告诉你哪些格子不能走了。
一开始和(1,1)在同一行和同一列的位置都置为1;遇到不能走的则停止置。
然后用递推公式
a[i][j] = (a[i-1][j]+a[i][j-1] )%100003递推即可。
【代码】
#include <cstdio> #include <cstring> int n,m,a[1001][1001] = {0}; bool bo[1001][1001]; void input_data() { memset(bo,true,sizeof(bo));//一开始置所有的点都可以走 scanf("%d%d",&n,&m); for (int i = 1;i <= m;i++) //输入m个不能走的点 并将其bo值置为false; { int x,y; scanf("%d%d",&x,&y); bo[x][y] = false; } for (int i = 1;i <= n;i++) //和(1,1)在同一行或同一列都只有一种到达方式。如果有不能走到的点 if (bo[1][i])//在这一行或一列上。它后面被挡住的点就无法到达了。 a[1][i] = 1; else break; for (int i = 1;i <= n;i++) if (bo[i][1]) a[i][1] = 1; else break; } void get_ans() //根据过河卒的思路来递推答案即可。 { for (int i = 2;i <= n;i++) for (int j = 2;j <= n;j++) if (bo[i][j]) a[i][j] = (a[i-1][j]+a[i][j-1]) % 100003; //要记住取模运算! } void output_ans() { printf("%d ",a[n][n]); } int main() { input_data(); get_ans(); output_ans(); return 0; }