(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;
}
(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;
}