题目
题意
有
n
n
个程序猿要写 行代码,第
i
i
个程序猿每行会出现 个
bug
b
u
g
,问最后总
bug
b
u
g
数不超过
b
b
的码代码方案数有多少种,答案对 取模
其中,方案定义为,每个程序猿码代码的行数,如果两种方案中,存在一人所码代码行数两次不同,则认为是两种方案。
思路
如果我们独立的看待每行代码,定义
dp[k][i][j]
d
p
[
k
]
[
i
]
[
j
]
为,前
i
i
个程序猿,一共写 行代码,恰好写了
j
j
个 的方案数,则有如下转移方程
含义为,遍历每一行代码,每加一行当前行对 i, j i , j 的影响是,仍由前 i−1 i − 1 个人写 j j 个 ,或者由第 i i 个人写 个 bug b u g ,而对应就要从所有 j−vi j − v i 个 bug b u g 处转移而来。然后由于第 k k 行只从第 行转移得到,所以可以使用滚动数组。当然也可以使用适当的遍历顺序改成二维的遍历,只是懒得想了= =
代码
int dp[2][maxn][maxn];
int v[maxn];
int main()
{
int n, m, b, mod, flag = 0;
sddd(n, m, b);
sd(mod);
rep(i, 1, n+1) sd(v[i]);
mm(dp, 0);
rep(i, 1, n+1){
dp[flag][i][v[i]]++;
rep(j, 0, m+1){
dp[flag][i][j] += dp[flag][i-1][j];
}
}
rep(cas, 1, m) { //m lines
flag ^= 1;
rep(i, 1, n+1) {
rep(j, 0, b+1) {
dp[flag][i][j] = dp[flag][i-1][j];
if(j >= v[i])
dp[flag][i][j] = (dp[flag][i][j] + dp[flag^1][i][j-v[i]])%mod;
}
}
}
int sum = 0;
rep(j, 0, b+1)
sum = (sum+dp[flag][n][j])%mod;
pd(sum);
}
思考
进行模型转化之后,这道题其实就是一个 dp d p 中的背包问题,把代码行数看成总的物品数, bug b u g 数看作是空间限制,人看作是物品。问恰好取 m m 个物品,总重量不超过 的取法总数