返回顶部

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;
    }
    
posted @ 2021-10-27 14:30  Rayotaku  阅读(204)  评论(0编辑  收藏  举报