传送门
题目:
示例1
输入
2 2 1 1
0 0
1 1
输出
2
示例2
输入
3 3 2 0
0 0 1
0 0 1
1 0 0
输出
6
题目大意:
给
出
n
×
m
的
地
图
,
其
中
每
个
格
子
上
存
1
/
0
,
求
从
(
1
,
1
)
到
(
n
,
m
)
的
路
径
中
所
有
满
足
0
的
个
数
至
少
有
p
个
、
1
的
个
数
至
少
有
q
个
的
路
径
总
数
给出 n\times m 的地图,其中每个格子上存1/0,求从(1,1)到(n,m)的路径中所有满足0的个数至少有p个、1的个数至少有q个的路径总数
给出n×m的地图,其中每个格子上存1/0,求从(1,1)到(n,m)的路径中所有满足0的个数至少有p个、1的个数至少有q个的路径总数
思路:
首
先
:
首先:
首先:
1.
如
果
用
d
f
s
去
寻
找
很
有
可
能
超
时
;
1.如果用dfs去寻找很有可能超时;
1.如果用dfs去寻找很有可能超时;
2.
如
果
d
p
用
四
维
数
组
分
别
存
放
x
轴
坐
标
、
y
轴
坐
标
和
0
、
1
的
个
数
那
么
会
超
内
存
2.如果dp用四维数组分别存放x轴坐标、y轴坐标和0、1的个数那么会超内存
2.如果dp用四维数组分别存放x轴坐标、y轴坐标和0、1的个数那么会超内存
所
以
:
所以:
所以:
需
要
我
们
换
个
角
度
去
解
题
;
需要我们换个角度去解题;
需要我们换个角度去解题;
由
分
析
我
们
可
以
发
现
,
无
论
走
哪
条
路
都
满
足
:
由分析我们可以发现,无论走哪条路都满足:
由分析我们可以发现,无论走哪条路都满足:
0
的
个
数
+
1
的
个
数
=
n
+
m
−
1
;
0的个数 +1 的个数 = n+m-1;
0的个数+1的个数=n+m−1;
由
此
可
得
:
1
的
个
数
=
(
n
+
m
−
1
)
−
0
的
个
数
由此可得:1的个数 = (n+m-1)-0的个数
由此可得:1的个数=(n+m−1)−0的个数
所
以
:
可
以
通
过
d
p
标
记
不
同
0
的
数
目
的
路
径
个
数
,
最
终
统
计
0
数
目
满
足
题
目
要
求
的
所
有
路
径
之
和
即
可
;
所以:可以通过dp标记不同0的数目的路径个数,最终统计0数目满足题目要求的所有路径之和即可;
所以:可以通过dp标记不同0的数目的路径个数,最终统计0数目满足题目要求的所有路径之和即可;
优
化
过
后
d
p
[
i
]
[
j
]
[
k
]
代
表
含
义
:
优化过后dp[i][j][k]代表含义:
优化过后dp[i][j][k]代表含义:
i
=
1
:
当
前
行
;
i
=
0
:
上
一
行
;
j
:
当
前
列
;
k
:
0
的
个
数
i=1:当前行; i=0:上一行; j:当前列;k:0的个数
i=1:当前行;i=0:上一行;j:当前列;k:0的个数
d
p
[
0
]
[
j
]
[
k
]
:
上
一
行
第
j
列
0
有
k
个
时
的
路
径
数
dp[0][j][k]: 上一行第j列0有k个时的路径数
dp[0][j][k]:上一行第j列0有k个时的路径数
d
p
[
1
]
[
j
]
[
k
]
:
当
前
行
第
j
列
0
有
k
个
时
的
路
径
数
dp[1][j][k]: 当前行第j列0有k个时的路径数
dp[1][j][k]:当前行第j列0有k个时的路径数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//#define int long long
const int N=1e3+10;
const int mod=998244353;
int a[510][510],dp[2][510][N];
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n,m,p,q;
cin>>n>>m>>p>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)cin>>a[i][j];
if(p+q>n+m-1){
cout<<0<<endl;return 0;
}
if(a[1][1]){//起点为1时
dp[1][1][0]=1;
}else dp[1][1][1]=1;//起点为0时
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==1&&j==1)continue;
if(a[i][j]){
for(int k=0;k<n+m;k++)//更新当列不同0个数时的路径数
dp[1][j][k]=(dp[1][j-1][k]+dp[0][j][k])%mod;
}else{
dp[1][j][0]=0;//当前第j列有0个0的路径数目为0
for(int k=1;k<n+m;k++){
dp[1][j][k]=(dp[1][j-1][k-1]+dp[0][j][k-1])%mod;
// cout<<dp[1][j][k]<<' ';
}
}
}
for(int j=1;j<=m;j++)//更新,将当前行置为下一次循环的上一行
for(int k=0;k<n+m;k++)dp[0][j][k]=dp[1][j][k];
}
ll ans=0;
for(int i=p;i<=m+n-1-q;i++)ans=(ans+dp[0][m][i])%mod;
cout<<ans<<endl;
return 0;
}