题目大意:给定一个 n × m n \times m n×m的 0 − 1 0-1 0−1矩阵,要求从左上角 ( 1 , 1 ) (1,1) (1,1)走到右下角 ( n , m ) (n, m) (n,m),路径上至少经过 p p p个 0 0 0, q q q个 1 1 1。求这样的路径有多少条。
思路分析: D P DP DP思路是队友给的,贴一个队友的博客:2021 ICPC 江西省 A. Mio visits ACGN Exhibition(DP,大离谱,经验分享)_yezzz的博客-CSDN博客
首先按照 D P DP DP的基本思路,用 d p [ i ] [ j ] [ x ] [ y ] dp[i][j][x][y] dp[i][j][x][y]表示到 ( i , j ) (i, j) (i,j)位置,走过了 x x x个 0 0 0和 y y y个 1 1 1。然后考虑数据规模,显然空间会爆掉(需要开 l o n g l o n g long\ long long long),那么考虑降维优化:
- y y y可以被压缩,因为由 ( 1 , 1 ) → ( i , j ) (1, 1) \rightarrow (i, j) (1,1)→(i,j)经过了 i + j i + j i+j步,其中有 x x x个 0 0 0,那么 y = i + j − 1 − x y = i + j - 1 - x y=i+j−1−x,即 y y y可以用前三维表示;
那么 d p [ i ] [ j ] [ x ] dp[i][j][x] dp[i][j][x]就可以表示到 ( i , j ) (i, j) (i,j)位置,走过了 x x x个 0 0 0和 i + j − 1 − x i + j - 1 - x i+j−1−x个 1 1 1。我们可以得出状态转移方程: d p [ i ] [ j ] [ x ] = { d p [ i ] [ j − 1 ] [ x ] + d p [ i − 1 ] [ j ] [ x ] , ( m p [ i ] [ j ] = = 1 ) d p [ i ] [ j − 1 ] [ x − 1 ] + d p [ i − 1 ] [ j − 1 ] [ x − 1 ] , ( m p [ i ] [ j ] = = 0 ) dp[i][j][x]= \begin{aligned} \begin{cases} dp[i][j - 1][x] + dp[i - 1][j][x],\ (mp[i][j] == 1) \\ dp[i][j - 1][x - 1] + dp[i - 1][j - 1][x - 1],\ (mp[i][j] == 0) \\ \end{cases} \end{aligned} dp[i][j][x]={dp[i][j−1][x]+dp[i−1][j][x], (mp[i][j]==1)dp[i][j−1][x−1]+dp[i−1][j−1][x−1], (mp[i][j]==0)
- 空间仍然不是最优的,仍然会卡空间。考虑继续降维优化:不难发现,自顶开始向下,每一行的状态在当前的循环中只会影响下一轮的状态,于是可以采用滚动数组法优化掉第一维度。 d p [ j ] [ x ] = { d p [ j − 1 ] [ x ] + d p [ j ] [ x ] , ( m p [ i ] [ j ] = = 1 ) d p [ j − 1 ] [ x − 1 ] + d p [ j − 1 ] [ x − 1 ] , ( m p [ i ] [ j ] = = 0 ) dp[j][x]= \begin{aligned} \begin{cases} dp[j - 1][x] + dp[j][x],\ (mp[i][j] == 1) \\ dp[j - 1][x - 1] + dp[j - 1][x - 1],\ (mp[i][j] == 0) \\ \end{cases} \end{aligned} dp[j][x]={dp[j−1][x]+dp[j][x], (mp[i][j]==1)dp[j−1][x−1]+dp[j−1][x−1], (mp[i][j]==0)
注意处理细节,极其容易被卡。
#include
#define int long long
#define MOD 998244353
using namespace std;
const int N = 1000 + 10;
int mp[N][N], dp[N][N], sto[N][N];
inline void solve(int ans = 0){
int n, m, p, q; cin >> n >> m >> p >> q;
for(int i = 1; i mp[i][j];
(!mp[1][1]) ? dp[1][1] = 1 : dp[1][0] = 1;
for(int i = 1; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?