卧薪尝胆,厚积薄发。
Writing Code
Date: Thu Jul 19 20:33:49 CST 2018
In Category:
NoCategory
Description:
有
$n$
个程序员,每个程序员可以写若干行代码,第
$i$
个程序员每行里会有
$a_i$
个
$bug$
,现在要完成一个恰好
$m$
行的代码且总
$bug$
数量不能超过
$b$
,求有多少种完成方案。
$1\le n,m \le 500$
Solution:
考虑每个程序员为一个阶段,决策时需要知道当前已完成的行数与
$bug$
数,
$f(i,j,k)$
表示前
$i$
个程序员共写了
$j$
行代码,产生
$bug$
数为
$k$
的方案数
$\begin{align}f(i,j,k) = \sum^j_{x=0} f(i−1,j−x,k−a_i\times x) \end{align}$
注意到这其实是个完全背包问题,考虑改写转移方程进行优化
$f(i,j,k) = f(i−1,j,k) +f(i,j−1,k−a_i) $
。滚动数组优化空间
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,b,MOD;
#define MAXN 510
int a[MAXN];
int f[2][MAXN][MAXN];
int main()
{
scanf("%d%d%d%d",&n,&m,&b,&MOD);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
int cur = 0;
f[0][0][0] = 1;
for(int i = 1;i <= n;++i)
{
cur = cur ^ 1;
for(int j = 0;j <= m;++j)
{
for(int k = 0;k <= b;++k)
{
f[cur][j][k] = f[cur ^ 1][j][k];
if(k >= a[i])f[cur][j][k] = (f[cur][j][k] + f[cur][j - 1][k - a[i]]) % MOD;
}
}
}
int ans = 0;
for(int i = 0;i <= b;++i)
{
ans = (ans + f[cur][m][i]) % MOD;
}
cout << ans << endl;
return 0;
}
In tag:
DP-DP
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡