计数动态规划(简称计数DP)是动态规划的一种应用领域,主要用于解决计数问题。计数问题是指需要计算某个特定事件的发生次数或满足特定条件的组合数目的问题。
计数 D P DP DP特点:
话不多说,我们直接看例题。
题目链接
对于5,我们有如下的划分:
联系我们之前学过的知识点,很容易想到完全背包。
完全背包模型与01背包类似,与01背包的区别仅在于一个物品可以选取无限次,而非仅能选取一次。
完全背包代码:
#include
using namespace std;
typedef pair PII;
#define int long long
#define endl '\n'
const int N = 3000;
int w[N], c[N], dp[N];
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int m, n;
cin >> m >> n;
for (int i = 1; i <= n; i++)
{
cin >> w[i] >> c[i];
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
dp[j] = max(dp[j], dp[j - w[i]] + c[i]);
}
}
return 0;
}
完全背包与01背包的代码实现区别:
v : 10 − 9 − 8 − 7 − 6 ∣ w [ i ] = 3 v: 10-9-8- 7 - 6 | w[i] = 3 v:10−9−8−7−6∣w[i]=3
更新公式: d p [ l ] = f [ l − w [ i ] ] + v [ i ] dp[l]=f[l - w[i]] + v[i] dp[l]=f[l−w[i]]+v[i]
变量 l l l倒序时:
更新的顺序: d p [ 10 ] , d p [ 9 ] , d p [ 8 ] , d p [ 7 ] dp[10],dp[9],dp[8],dp[7] dp[10],dp[9],dp[8],dp[7]
变量 l l l顺序时:
更新: d p [ 3 ] , d p [ 4 ] , d p [ 5 ] , d p [ 6 ] , d p [ 7 ] dp[3],dp[4],dp[5],dp[6],dp[7] dp[3],dp[4],dp[5],dp[6],dp[7]
差别:使用顺序的时候,每次更新采用这一轮被更新过的值
下面附上代码
#include
#define int long long
#define endl '\n'
using namespace std;
typedef pair PII;
const int N = 3000;
const int P = 1e9 + 7;
int f[N];
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n;
cin >> n;
f[0] = 1;
for (int i = 1; i <= n; i++){
for (int j = i; j <= n; j++){
f[j] = (f[j] + f[j - i]) % P;
}
}
cout << f[n] % P;
return 0;
}
#include
using namespace std;
#define endl '\n'
#define int long long
#define PII pair
#define For(i, a, b) for (int i = a; i <= b; i++)
const int N = 1e6;
const int M = 1e4;
const int MOD = 998244353;
int n, a[N];
int x, y;
int fac[N], inv[N];
int dp[M][M];
int quick_power(int a, int k, int p)
{
int ans = 1;
while (k)
{
if (k & 1)
ans = ans * a % p;
k >>= 1;
a = a * a % p;
}
return ans;
}
void init()
{
inv[0] = inv[1] = 1;
fac[0] = fac[1] = 1;
for (int i = 2; i <= 200010; ++i)
{
fac[i] = (fac[i - 1] * i) % MOD;
inv[i] = quick_power(fac[i], MOD - 2, MOD);
}
}
int C(int n, int m)
{
return fac[n] * inv[m] % MOD * inv[n - m] % MOD;
}
void problem_solved(){
dp[0][0] = 1;
For (i, 0, x){
For (j, 0, y){
if (i >= j){
if (x - i >= y - j){
dp[i][j + 1] = (dp[i][j + 1] + dp[i][j]) % MOD;
dp[i + 1][j] = (dp[i + 1][j] + dp[i][j]) % MOD;
}
}
}
}
cout << dp[x][y] << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
init();
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (a[i] == 1)
{
x++;
}
else
{
y++;
}
}
if (x <= y)
{
cout << C(y + 1, x) << endl;
return 0;
}
problem_solved();
return 0;
}
今天的文章就到这里啦,三连必回qwq!