二:程序编写题
题目名称:小田的活动安排
题目描述:小田同学考试考了第一,妈妈奖励他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用1-5表示,第5等最重要。他从网上查到每件物品的价格(都是整数元)。他希望在不超N元的前提下,使得每件物品的价格与重要度的乘积总和最大。设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,...,jk,则所求的总和为:v[j1]*w[j1]+v[j2]*w[j2]+...+v[jk]*w[jk].请你帮小田设计一个满足要求的购物单。
输入描述:第一行,为2个整数n和m,用空格隔开,n为总钱数,m为希望购买物品的个数。接下来M行,给出相对应的物品数据,每行有两个非负整数v和p,v是价格,p是重要度(1-5).
输出描述:1个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值。
样例输入:
1000 5
800 2
400 5
300 5
400 3
200 2
经典的01背包问题,使用动态规划求解,C++代码如下:
#include <bits/stdc++.h> // C++万能头文件
using namespace std;
using pii = pair<int, int>; // 每个物品的价格和重要度
int main() {
int n, m; // 商品总钱数和个数
cin >> n >> m;
vector<pii> items; // 记录m件商品
for (int i = 0; i < m; ++i) {
int v, p; // 价格和重要度
cin >> v >> p;
items.emplace_back(v, p);
}
// dp[i][j]表示在前i件商品中选择,总价格不超过j的最大价格与重要度的乘积和
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 1; i <= m; ++i) {
auto [v, p] = items[i - 1]; // 当前商品的价格和重要度
for (int j = 1; j <= n; ++j) {
if (j < v) // 当前商品价格超过限制,不选
dp[i][j] = dp[i - 1][j];
else // 当前商品可选,取选或不选两者的较大值
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v] + v * p);
}
}
int k = 0; // 统计所选商品的个数
vector<bool> selected(m); // 标记选择哪些商品
for (int i = m, j = n; i >= 1; --i) {
if (dp[i][j] > dp[i - 1][j]) {
selected[i - 1] = true; // 选择该商品
++k;
j -= items[i - 1].first;
}
}
cout << "共选了" << k << "件商品,最大价格与重要度的乘积和为" << dp[m][n] << "\n";
cout << "所选商品的价格和重要度分别为:\n";
for (int i = 0; i < m; ++i) {
if (selected[i])
cout << items[i].first << " " << items[i].second << "\n";
}
return 0;
}
实例输出结果为:
如果能帮到你,给个采纳哈~