A. Mio visits ACGN Exhibition
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
One day, Mio visits an Animation Comic Game Novel (ACGN) Exhibition, and she would like to buy some presents for Ritsu.
We assure that the space of the exhibition is a n×mn×m grid, called the grid AA, and each cell in the grid represents a stall, only selling present 00 or 11. In other words, every cell of the n×mn×m grid AA is filled with 00 or 11.
Under the control policy for containing COVID-19, there are some restrictions on visiting route.
We define a SAFE PATH as a path from the top left cell (1,1)(1,1), to the bottom right cell (n,m)(n,m), and if you are in the cell (x,y)(x,y), then you can only travel to the cells (x+1,y)(x+1,y) or (x,y+1)(x,y+1). Every visitor has to visit the exhibition through SAFE PATH, so does Mio.
The two paths are considered to be different if and only if at least one cell passed differs.
Mio wonders how many different SAFE PATHs, which have some 00s and 11s, and the number of 00 is at least pp, the number of 11 is at least qq.
Since the answer may be too large, you only need to output the result modulo 998244353998244353.
Input
The first line contains four integers, nn, mm, pp, qq (1≤n,m≤500,0≤p,q≤100001≤n,m≤500,0≤p,q≤10000).
Each of the next nn lines contains mm space separated integers Ai,jAi,j (0≤Ai,j≤1)(0≤Ai,j≤1), denoting the number in the cell (i,j)(i,j) of the grid AA.
Output
Print a single integer, denoting the answer to the question, modulo 998244353998244353.
Examples
input
Copy
2 2 1 1 0 0 1 1
output
Copy
2
input
Copy
3 3 2 0 0 0 1 0 0 1 1 0 0
output
Copy
6
题意:一个n * m 的矩阵,矩阵由0和1构成,p,q分别代表从(1,1)这一点到(n,m)这一点,需要经过的至少0,1个数,问这样的路径有几条,
用dfs对于本题来说是2的n次方,绝对超时,这时就要想和dfs捆绑的动态规划,动态规划可以将时间压缩很多,可以写三维的动态规划方程,dp[i][j][k], i代表的是从哪一行转移,j代表的是从哪一列转移,k代表的是到dp[i][j]走过的0的个数,dp[i][j][k]的值代表的是走过k个0的路径总数。
搞清楚各个下标的含义,构造dp就看需要什么,就构造几维。
注意到,其实转移只可能是从当前点所在行的上一行,和当前行两行转移,那么可以把i改成2,就两种状态,初始状态,当第一个点为1,那么,dp[1][1][0] = 1, 第一个1也可以是0,随便假设,第二个就是列数,第三个就是走过0个0,反之dp[1][1][1] = 0;
最后就是遍历从k = p; n +m - 1 - k >= q; ++k
状态转移 当当前点是0时 dp[i][j][k] = dp[i][j - 1][k - 1] + dp[i ^ 1][j][k - 1]等于可以走到他的两个路径总数相加,当当前点是1时dp[i][j][k] = dp[i][j - 1][k] + dp[i ^ 1][j][k]等于简单的相加。
其实想到以上看着简单,但其实还是有难度的,首先是三维,还有就是最后一维是记录走过了几个0,最后一步这个遍历想到最后来处理,也是很难想到的,但其实是一环扣一环,还是按照题目意思来,他要求几个,那我就要记录下来,然后遍历。
最后就是用long long 会超时,以后能不用long long 就别用
#include <bits/stdc++.h>
//#define int long long
#define ISO ios::sync_with_stdio(false)
using namespace std;
const int N = 5e2 + 10;
const int mod = 998244353;
int n, m, p0, q1;
int a[N][N];
int dp[2][N][2 * N + 10];// 值为路径数
signed main()
{
ISO; cin.tie(0), cout.tie(0);
cin >> n >> m >> p0 >> q1;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
cin >> a[i][j];
}
int s = 1;
if (a[1][1] == 1)
dp[1][1][0] = 1;
else
dp[1][1][1] = 1;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (i == 1 && j == 1)
continue;
for (int k = 0; k <= n + m - 1; ++k)
{
if (a[i][j] == 1)
{
dp[s][j][k] = dp[s ^ 1][j][k] + dp[s][j - 1][k];
}
else if (a[i][j] == 0)
{
dp[s][j][k] = dp[s ^ 1][j][k - 1] + dp[s][j - 1][k - 1];
}
dp[s][j][k] = dp[s][j][k] % mod;
}
}
s = s ^ 1;
}
s = s ^ 1;
int ans = 0;
for (int k = p0; n + m - k - 1 >= q1; ++k)
{
ans = ans + dp[s][m][k];
ans = ans % mod;
}
cout << ans << endl;
return 0;
}