方案数问题dp

(1).4727. 摆放棋子 - AcWing题库

        (2)解题思路

                考虑dp状态dp[i][j][w1][w2],表示当前黑子还剩多少,白子还剩多少,末尾有w1个黑子,w2个白子。

                直接记忆化搜索即可。

        (3)代码实现

// Problem: 摆放棋子
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/4730/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 1e2 + 10;
const int mod = 1e8;
int dp[N][N][12][12];
int n1, n2, k1, k2;
int dfs(int d1, int d2, int w1, int w2)
{
    if (!d1 && !d2)
        return 1;
    if (dp[d1][d2][w1][w2] != -1)
        return dp[d1][d2][w1][w2];
    int res = 0;
    if (d1 && w1 + 1 <= k1)
        res += dfs(d1 - 1, d2, w1 + 1, 0);
    if (d2 && w2 + 1 <= k2)
        res += dfs(d1, d2 - 1, 0, w2 + 1);
    return dp[d1][d2][w1][w2] = res % mod;
}
void solve()
{
    cin >> n1 >> n2 >> k1 >> k2;
    memset(dp, -1, sizeof(dp));
    cout << dfs(n1, n2, 0, 0) << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}

2.Problem - C - Codeforces

        (1)题目大意

                给你一个正数n,你需要去计算满足一下条件的字符串(只有0和1)的数量,对于每一对(i,j)// 0表示无所谓,1表示相同,2表示有两个不相同。

         (2)解题思路

                因为0操作没有约束,我们不需要管他,对于1而言,要求[i,j]要相同,因此我们考虑r[i] = max(r[i],j),对于2而言,要求[i,j]中至少要有一个不同,因此我们考虑l[j] = max(l[j],i),然后我们定义dp[i][j]表示第i位选0或者选1的方案数,然后第二层j从i向n枚举,若对于前面最大的l[j]都<j,并且r[j - 1] < j说明j-1这个位置在i的限制下随便选什么。最后答案就是dp[n][0] + dp[n][1]

        (3)代码实现

// Problem: C. Count Binary Strings
// Contest: Codeforces - Educational Codeforces Round 140 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1767/problem/C
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 1e2 + 10;
ll dp[N][2];
int r[N], l[N];
// 0表示无所谓,1表示相同,2表示有两个不相同
const int mod = 998244353;
void solve()
{
    int n, x;
    cin >> n;
    dp[0][0] = dp[0][1] = 1;
    for (int i = 1; i <= n; i++)
    {
        for (int j = i; j <= n; j++)
        {
            cin >> x;
            if (x == 1)
                r[i] = max(r[i], j);
            else if (x == 2)
                l[j] = max(l[j], i);
        }
    }
    //r表示最多能和右边多少个必须一致
    //l表示最少要和左边多少个必须一致
    for (int i = 1; i <= n; i++)
    {
        r[i] = max(r[i], r[i - 1]);
    }
    for (int i = 1; i <= n; i++)
    {
        int ml = 0;
        for (int j = i; j >= 1; j--)
        {
            ml = max(ml, l[j]);
            if (ml < j && r[j - 1] < j)
            {
                dp[i][0] += dp[j - 1][1];
                dp[i][1] += dp[j - 1][0];
            }
            dp[i][0] %= mod;
            dp[i][1] %= mod;
        }
    }
    cout << max(0LL, (dp[n][0] + dp[n][1])) % mod << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值