zoukankan      html  css  js  c++  java
  • 【洛谷U142297】下棋

    题目:

    题目链接:https://www.luogu.com.cn/problem/U142297
    (n) 个白色棋子,(m) 个黑色棋子,现在需要把他们排成一排,要求对于任意一段棋子,其中的白色棋子和黑色棋子的差不能超过 (t),求棋子排列方案数对 (10^9+7) 取模的结果。
    (n,mleq 150,tleq 20)

    思路

    假设我们目前取了 (i) 个黑棋和 (j) 个白棋,在上一次取棋之前都是满足白色棋子和黑色棋子的差不超过 (k),那么如何判断此时黑白棋子的差是否超过 (k)
    我们可以分成黑减白以及白减黑两种方法计算,以黑减白为例,我们知道此时 (i-j) 的值,我们需要知道前面是否存在某一个时刻黑白棋子分别有 (i',j') 个,且满足 ((i-i')-(j-j')>k)
    显然上式等价于 ((i-j)+(j'-i')>k),所以我们只需要知道之前白棋减黑棋的最大值即可判断。
    所以设 (f[i][j][k][l]) 表示取了 (i) 个黑棋,(j) 个白棋,之前黑减白最大值为 (k),白减黑最大值为 (l) 的方案数。
    转移就分下一个棋子取黑棋还是白棋即可。以拿黑棋来说,有

    [f[i+1][j][max(k,i+1-j)][l]gets f[i][j][k][l] ]

    时空复杂度均为 (O(nmt^2))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=160,M=25,MOD=1e9+7;
    int n,m,t,ans,f[N][N][M][M];
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&t);
    	f[0][0][0][0]=1;
    	for (int i=0;i<=n;i++)
    		for (int j=0;j<=m;j++)
    			for (int k=0;k<=t;k++)
    				for (int l=0;l<=t;l++)
    				{
    					if (i-j+l>t || j-i+k>t)	f[i][j][k][l]=0;
    					if (i+1-j+l<=t && i<n)
    						f[i+1][j][max(i+1-j,k)][l]=(f[i+1][j][max(i+1-j,k)][l]+f[i][j][k][l])%MOD;
    					if (j+1-i-k<=t && j<m)
    						f[i][j+1][k][max(j+1-i,l)]=(f[i][j+1][k][max(j+1-i,l)]+f[i][j][k][l])%MOD;
    				}
    	for (int i=0;i<=t;i++)
    		for (int j=0;j<=t;j++)
    			ans=(ans+f[n][m][i][j])%MOD;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    学习H5一周随笔
    vue项目中vux的使用
    git操作常用命令
    vue2.0 实现全选和全不选
    鼠标事件以及clientX、offsetX、screenX、pageX、x的区别
    js编写当天简单日历
    UIView.frame的骗局
    设计模式笔记感悟
    实用图像处理入门
    实用图像处理入门
  • 原文地址:https://www.cnblogs.com/stoorz/p/14036071.html
Copyright © 2011-2022 走看看