zoukankan      html  css  js  c++  java
  • 2019牛客多校第一场E ABBA 贪心 + DP

    题意:问有多少个有(n + m)个A和(n + m)个B的字符串可以凑出n个AB和m个BA。

    思路:首先贪心的发现,如果从前往后扫,遇到了一个A,优先把它看成AB的A,B同理。这个贪心策略用邻项交换很好证明。之后,我们设dp[i][j]为填了i个A和j个B的字符串不违法的方案数。什么叫不违法呢?有一些方案是一定不可以凑出n个AB和m个BA的,比如如果i - n > j了就不行:现在已经有i个A,其中有n个A用来充当AB的A,那么剩下的A只能去充当BA的A,但是假如现在你的B的个数j小于的BA的A的个数,那么你后面有多少个B都于事无补了,一定会少一个BA。所以状态必须满足两个不等式:i - n <= j, j - m <= i。只要满足这两个条件,状态直接转移就可以了。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 2010;
    const LL mod = 1e9 + 7;
    LL dp[maxn][maxn];
    int n, m, x, y;
    bool valid(int A, int B) {
    	return (B >= A - n) && (A >= B - m);
    }
    void solve() {
    	for (int i = 0; i <= n + m; i++) {
    		for (int j = 0; j <= n + m; j++) {
    			dp[i][j] = 0;
    			if(i == 0 && j == 0) dp[i][j] = 1;
    			if(!valid(i, j)) continue;
    			if(j) dp[i][j] += dp[i][j - 1];
    			if(i) dp[i][j] += dp[i - 1][j];
    			dp[i][j] %= mod;
    		}
    	}
    	printf("%lld
    ", dp[n + m][n + m]);
    }
    int main() {
    	while(~scanf("%d%d", &n, &m)) {
    		solve();
    	}
    }
    

      

  • 相关阅读:
    感觉跟奇怪
    人多
    淡忘
    可疑
    js判断对象是否为空对象的几种方法
    互联网隐私泄漏
    清明时节
    垃圾mac
    【ES6】---JavaScript(二)
    【微信小程序】---Socket聊天功能实现
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11212372.html
Copyright © 2011-2022 走看看