题目
TUOJ
https://sim.csp.thusaac.com/contest/37/problem/1
思路
DP,完全背包问题
代码
可以让AI总结一下代码逻辑
这是一个完全背包问题的解法,用于计算在给定重量限制下能获得的最大价值。
一、问题背景
-
有
n种石头,每种石头有固定的重量和价值 -
总重量限制为
m -
每种石头可以无限次选取(完全背包特征)
二、数据设定
-
v[i]:第 i 种石头的价值 -
w[i]:第 i 种石头的重量(这里设w[i] = i,即第 i 种石头的重量就是 i) -
f[j]:重量限制为 j 时能获得的最大价值
三、核心逻辑
1. 输入处理
-
先读入总重量限制
m和石头种类数n -
然后读入每种石头的价值
v[i] -
每种石头的重量
w[i]直接设为i(第 i 种石头重量为 i)
2. 动态规划求解
cpp
for(int i=1;i<=n;i++) // 遍历每种石头
for(int j=w[i];j<=m;j++) // 遍历重量(从小到大)
f[j] = max(f[j], f[j-w[i]] + v[i]);
-
外层循环:依次考虑每种石头
-
内层循环:从小到大遍历重量
-
状态转移:对于当前重量 j,可以选择:
-
不选当前石头:保持
f[j] -
选一个当前石头:价值增加
v[i],重量减少w[i]
-
3. 输出结果
输出 f[m],即总重量限制为 m 时的最大价值
四、关键特点
-
完全背包特征:内层循环从小到大(区别于 01 背包的从大到小)
-
重量等于编号:第 i 种石头的重量就是 i
-
一维优化:使用滚动数组,空间复杂度 O(m)
cpp
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N=10005;
int f[N],v[N],w[N];
void solve()
{
int n,m; cin>>m>>n; //m 总个数 n 石头种数
for(int i=1;i<=n;i++)
{
cin>>v[i];
w[i]=i;
}
for(int i=1;i<=n;i++)
for(int j=w[i];j<=m;j++)
f[j]=max(f[j],f[j-w[i]]+v[i]);
cout<<f[m]<<endl;
}
int main()
{
cin.tie(0);
solve();
return 0;
}
/*
10 5
1 3 5 3 1
4 3
1 60 100
*/