Loading

CodeForces-118D Caesar's Legions

Caesar's Legions

记忆化搜索

\(dp[i][j][k]\) 表示当前有 \(i\) 个步兵,\(j\) 个骑兵,同时当前的兵种(第 \(i+j\) 个)是步兵(0) 或 骑兵(1)

假设当前兵种是步兵,则可以进行记忆化搜索

\(dp[i][j][0] = \sum_{x=1}^{min(k_2, j)}(dps(i, j-x, 1))\)

同时限制骑兵的数量不大于 \(k_2\)

同理,如果当前兵种是骑兵,则有:

\(dp[i][j][1] = \sum_{x=1}^{min(k_1, i)}(dps(i - x, j, 0))\)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e8;
ll dp[110][110][2];
int n1, n2, k1, k2;

ll dps(int x, int y, int t)
{
    if(dp[x][y][t] != -1) return dp[x][y][t];
    if(x == 0 && y == 0) return dp[x][y][t] = 1;
    dp[x][y][t] = 0;
    ll &ans = dp[x][y][t];
    if(t == 0)
    {
        for(int i=1; i<=min(y, k2); i++)
            ans = (ans + dps(x, y-i, 1)) % mod;
    }
    else
    {
        for(int i=1; i<=min(x, k1); i++)
            ans = (ans + dps(x-i, y, 0)) % mod;
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n1 >> n2 >> k1 >> k2;
    for(int i=0; i<=n1; i++) for(int j=0; j<=n2; j++) dp[i][j][0] = dp[i][j][1] = -1;
    cout << (dps(n1, n2, 0) + dps(n1, n2, 1)) % mod << endl;
    return 0;
}

如果你一直 TLE,可以继续往下看

\(dp\) 状态虽然不多,但是存在着许多无效状态,即本身 \(dp[i][j][k] = 0\),因此我们要将所有 \(dp\) 数组初始化为 \(-1\)

可以尝试一下利用下方代码输入 10 10 2 2,就会发现大量值为 \(0\) 的状态被重复计算

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <array>
#include <map>
using namespace std;
typedef long long ll;
const ll mod = 1e8;
ll dp[110][110][2];
int n1, n2, k1, k2;
map<array<int, 3>, int>mp;

ll dps(int x, int y, int t)
{
    if(dp[x][y][t]) return dp[x][y][t];
    if(x == 0 && y == 0) return dp[x][y][t] = 1;
    dp[x][y][t] = 0;
    mp[{x, y, t}]++;
    ll &ans = dp[x][y][t];
    if(t == 0)
    {
        for(int i=1; i<=min(y, k2); i++)
            ans = (ans + dps(x, y-i, 1)) % mod;
    }
    else
    {
        for(int i=1; i<=min(x, k1); i++)
            ans = (ans + dps(x-i, y, 0)) % mod;
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n1 >> n2 >> k1 >> k2;
    cout << (dps(n1, n2, 0) + dps(n1, n2, 1)) % mod << endl;
    for(auto [a, d] : mp)
    {
        if(d > 1)
            cout << a[0] << " " << a[1] << " " << a[2] << ": " << d << endl;
    }
    return 0;
}
posted @ 2022-07-27 21:06  dgsvygd  阅读(139)  评论(0编辑  收藏  举报