Description
对于下述条件计算恋恋拿到礼物有几种走法。
给一个N*M的图,恋恋起始在左上角,坐标(1,1),面向右或者面向下,礼物坐标在(X,Y),图以外的区域全是洞,图以内还有K个洞,所有在洞上的东西都会掉下去,包括道具和路标。小五现在没有道具可以使用,但是有无限个指向右的路标和无限个指向下的路标可以使用。
小五可以在任意空地上放置道具和路标,恋恋只会无意识的向前走。
如果恋恋前面一格有路标,恋恋就会看一样路标,并往路标指的方向走。
如果恋恋前面一格的路标的指向和恋恋的走向一样,恋恋就会无视它,并且踩过去。
如果恋恋当前格子是洞,恋恋就会掉下去。
Input
输入数据第一行有三个整数N、M、K、X、Y(3<=N,M<1000,0<=K<n*m,1<=x<=n,1<=y<=m)
以下有K行,每行有两个整数Xi、Yi(1<=Xi<=N,1<=Yi<=M)第i个洞的坐标为(Xi,Yi)
数据保证每个洞和恋恋和礼物的位置均不同
Output
输出恋恋拿到礼物的走法数mod 10007的余数
Sample Input
4 4 1 3 4
2 2
Sample Output
2
Hint
样例中恋恋的两种走法分别是:
1.下下右右右
2.右右下下右
动态规划,每个位置有向右,向下两种状态.状态仅向右和向下转移,检查状态转移的合法性,瞎写一下。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define for1(i, n) for (int i = 1; i <= n; i++)
// head
const int mod = 10007;
const int maxn =1005;
int dp[maxn][maxn][2];
int vi[maxn][maxn];
int main() {
int n, m, k, x, y, xi, yi;
cin>> n >> m >> k >> x >> y;
for1(i, k) cin >> xi >> yi, vi[xi][yi] = 1;
for1(i, n) vi[i][m + 1] = 1;
for1(i, m) vi[n + 1][i] = 1;
//初始化状态转移
if(!vi[1][2]) dp[1][2][1] = 1;
if(!vi[2][1]) dp[2][1][0] = 1;
//0 向下 1 向右 dp[i][j][0] 表示达到(i,j)时状态为向下的方案数
for1(i, n)
for1(j, m) {
if(i == 1 && j == 1) {continue;}
if(dp[i][j][0]) {
if(!vi[i + 1][j])
dp[i + 1][j][0] = (dp[i + 1][j][0] + dp[i][j][0]) %mod;
if(!vi[i + 1][j] && !vi[i][j + 1])
dp[i][j + 1][1] = (dp[i][j + 1][1] + dp[i][j][0]) %mod;
}
if(dp[i][j][1]) {
if(!vi[i][j + 1])
dp[i][j + 1][1] = (dp[i][j + 1][1] + dp[i][j][1]) %mod;
if(!vi[i][j + 1] && !vi[i + 1][j])
dp[i + 1][j][0] = (dp[i + 1][j][0] + dp[i][j][1]) %mod;
}
}
cout<<(dp[x][y][0] + dp[x][y][1]) %mod<<endl;
return 0;
}