2021 Jiangxi Provincial Collegiate Programming Contest A. Mio visits ACGN Exhibition (dp)
-
题意:\(n\)x\(m\)的01矩阵,每次可以向下或向右移动,从\((1,1)\)走到\((n,m)\),且满足路径上的\(0\)的个数不少于\(p\),\(1\)的个数不小于\(q\),问你有多少条不同的路径数。
-
题解:设\(dp[i][j][k]\)表示在\((i,j)\),当前路径有\(k\)个\(0\)的方案数,这很简单,裸dp,
\(\begin{equation} \begin{cases} dp[i][j][k]=dp[i-1][j][k-1]+dp[i][j-1][k-1],\ (i,j)=0 \\ dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k],\ (i,j)=1 \end{cases} \end{equation}\)
时间复杂度\(O(n*m(n+m))\)也说的过去,但是爆空间了,但是不难发现,我们只用到了当前行和上一行的状态,那么可以将\(dp\)数组第一维优化掉,得到\(dp[now][j][k]\),\(now\)表示当前行,\(now\oplus 1\)表示上一行。
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 998244353; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b%mod;} int n,m,p,q; int a[505][505]; int dp[2][505][1005]; int main() { scanf("%d %d %d %d",&n,&m,&p,&q); for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ scanf("%d",&a[i][j]); } } int row=1; dp[1][1][0]=1; for(int i=1;i<=n;++i){ row^=1; for(int j=1;j<=m;++j){ for(int k=0;k<n+m;++k){ if(a[i][j]==0){ if(k) dp[row][j][k]=(dp[row^1][j][k-1]+dp[row][j-1][k-1])%mod; else dp[row][j][k]=0; //don't forget to set 0,cuz we initialized the dp[1][1][0]=1. } else if(a[i][j]==1){ dp[row][j][k]=(dp[row^1][j][k]+dp[row][j-1][k])%mod; } } } } ll ans=0; for(int i=p;i<n+m-q;++i) ans=(ans+dp[row][m][i])%mod; printf("%lld\n",ans); return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮