【动态规划】洛谷_1077 摆花

题意

给出NNN种花,其中第iii种花的数量不能超过aia_iai个,求一共摆MMM个花的方案数模1000007。

思路

动态规划。设f[i][j]f[i][j]f[i][j]为前iii种花摆jjj个的方案数,可得动态转移方程:
f[i][j]+=f[i][j−k]{k&lt;=a[i]}f[i][j]+=f[i][j-k]\{k&lt;=a[i]\}f[i][j]+=f[i][jk]{k<=a[i]}

代码

#include<cstdio>

int N, M;
int a[1001], f[1001][1001];

int main() {
	scanf("%d %d", &N, &M);
	for (int i = 1; i <= N; i++) scanf("%d", &a[i]);
	f[0][0] = 1;
	for (int i = 1; i <= N; i++)
		for (int j = 0; j <= M; j++)
			for (int k = 0; k <= a[i]; k++)
				f[i][j] = (f[i][j] + f[i - 1][j - k]) % 1000007;
	printf("%d", f[N][M]);
}
### 关于01背包问题的动态规划解法 #### 定义状态变量 对于01背包问题,在洛谷平台上的题目通常会定义一个二维数组`dp[i][j]`,其中`i`代表前`i`件物品,`j`表示当前剩余的空间大小。该数组用来存储在只考虑前`i`个物品的情况下,当背包容量为`j`时所能获得的最大价值[^1]。 #### 初始化边界条件 初始化阶段主要是设置好`dp[0][..]`以及`dp[..][0]`的状态。因为没有任何物品放入背包(`i=0`)或背包容量为零(`j=0`)的时候,能够获取到的价值自然也为零。所以有: ```cpp for (int i = 0; i <= n; ++i) dp[i][0] = 0; for (int j = 0; j <= V; ++j) dp[0][j] = 0; ``` 这里假设共有`n`种不同类型的物品可以选择,并且背包总容量为`V`[^3]。 #### 状态转移方程 核心部分在于如何更新状态矩阵中的各个元素值。对于每一件新加入考量范围内的商品而言(即第`i`项),存在两种可能性:要么这件商品不被选入最终方案;要么它会被选中并占用一定的空间从而带来额外收益。因此可以得到如下递推关系式: 如果选择第`i`个物品,则`dp[i][j]=max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])`,这里的`w[]`和`v[]`分别记录着各项目的重量及其对应的价值[^2]。 上述表达式的含义是说,在处理完前`i-1`个项目之后再来看待新增加进来的一个项目时,应该比较这两种情况哪个更优——既可以直接继承之前的结果而不做任何改变;也可以尝试把新的东西放进去看看能否提高整体效益。 #### 实现代码片段 下面是基于以上分析编写的简单实现版本(C++): ```cpp #include <iostream> using namespace std; const int MAXN = 1e3 + 5; int w[MAXN]; // 物品体积/时间消耗 int v[MAXN]; // 物品价值 int dp[MAXN][MAXN]; // 输入数据函数省略... void solve(int N, int T){ for(int i = 1 ; i<= N;i++){ for(int t = 0;t<=T;t++){ if(t<w[i]) dp[i][t]=dp[i-1][t]; else{ dp[i][t]= max(dp[i-1][t],dp[i-1][t-w[i]]+v[i]); } } } } int main(){ int N,T; cin>>N>>T; // 数据读取... solve(N,T); cout<<dp[N][T]<<endl; } ``` 此段程序实现了基本版别的01背包算法逻辑,适用于解决类似于洛谷平台上提到的那种具有固定数量物品与限定时间框架内寻求最大效用的问题实例[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值