小庄在一次机缘巧合的机会,眼睛获取了黄金瞳,黄金瞳的功能是可以看到m种物品10天以后的价格。但是这些物品属于限购物资,最多只能购买一定的数量。现在小庄有资金x可以投资这些物品,如何操作才能实现10天后资产价值最大。
第一行 当前资金 x
第二行物品种类m
第三行每种物品限购数量,m个数字
第四行物品当前价格,m个数字
第五行物品10天后价格,m个数字
10天后资产价值最大值
11 2 6 5 3 2 5 3
18
第一种物品买3个,第二种物品买1个,初期资产3*3+2*1=11,10天后资产价值最大5*3+3*1=18
import java.util.Scanner;
import java.util.Arrays;
class Item {
public int limit;
public int cur;
public int future;
public Item(int limit){
this.limit = limit;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int m = sc.nextInt();
Item[] items = new Item[m];
for(int i = 0; i < m; i++){
items[i] = new Item(sc.nextInt());
}
for(int i = 0; i < m; i++){
items[i].cur = sc.nextInt();
}
for(int i = 0; i < m; i++){
items[i].future = sc.nextInt();
}
int[][] dp = new int[m][x + 1];
System.out.println(Math.max(x, dfs(items, 0, x, dp)));
}
private static int dfs(Item[] items, int index, int rest, int[][] dp) {
if(index == items.length || rest < items[index].cur){
// 钱不够或物品到头了,后面都无法再产生收益
return 0;
}
if(dp[index][rest] > 0){
return dp[index][rest];
}
// 不选当前物品
int p1 = dfs(items, index + 1, rest, dp);
// 选当前物品
int p2 = 0;
for(int nums = 0; nums <= items[index].limit && nums * items[index].cur <= rest; nums++){
p2 = Math.max(p2, nums * items[index].future + dfs(items, index + 1, rest - nums * items[index].cur, dp));
}
dp[index][rest] = Math.max(p1, p2);
return dp[index][rest];
}
} 根据记忆化搜索可以改出动态规划,其实就是个背包问题 import java.util.Scanner;
import java.util.Arrays;
class Item {
public int limit;
public int cur;
public int future;
public Item(int limit){
this.limit = limit;
}
}
public class Main {
static int maxProfit = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int m = sc.nextInt();
Item[] items = new Item[m];
for(int i = 0; i < m; i++){
items[i] = new Item(sc.nextInt());
}
for(int i = 0; i < m; i++){
items[i].cur = sc.nextInt();
}
for(int i = 0; i < m; i++){
items[i].future = sc.nextInt();
}
int[] dp = new int[x + 1];
for(int index = 0; index < m; index++){
for(int rest = x; rest >= items[index].cur; rest--){
int p = 0;
for(int nums = 0; nums <= items[index].limit && nums * items[index].cur <= rest; nums++){
p = Math.max(p, rest + nums * items[index].future + dp[rest - nums * items[index].cur]);
}
dp[rest] = Math.max(dp[rest], p);
}
}
System.out.println(dp[x]);
}
} ===========================分割线============================= import java.util.Scanner;
import java.util.Arrays;
class Item {
public int limit;
public int cur;
public int future;
public Item(int limit){
this.limit = limit;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int m = sc.nextInt();
Item[] items = new Item[m];
for(int i = 0; i < m; i++){
items[i] = new Item(sc.nextInt());
}
for(int i = 0; i < m; i++){
items[i].cur = sc.nextInt();
}
for(int i = 0; i < m; i++){
items[i].future = sc.nextInt();
}
int[][] dp = new int[m][x + 1];
System.out.println(Math.max(x, dfs(items, 0, x, dp)));
}
private static int dfs(Item[] items, int index, int rest, int[][] dp) {
if(index == items.length || rest < items[index].cur){
// 钱不够或物品到头了,后面都无法再产生收益,直接返回剩下的钱
return rest;
}
if(dp[index][rest] > 0){
return dp[index][rest];
}
// 不选当前物品
int p1 = dfs(items, index + 1, rest, dp);
// 选当前物品
int p2 = 0;
for(int nums = 0; nums <= items[index].limit && nums * items[index].cur <= rest; nums++){
p2 = Math.max(p2, nums * items[index].future + dfs(items, index + 1, rest - nums * items[index].cur, dp));
}
dp[index][rest] = Math.max(p1, p2);
return dp[index][rest];
}
} 动态规划也要做出相应的修改,这里就不写了 import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int m = sc.nextInt();
// products[i][0]:限购数量,products[i][1]:当前价格,products[i][2]:10天后价格
int[][] products = new int[m][3];
for (int j = 0; j < 3; j++) {
for (int i = 0; i < m; i++) {
products[i][j] = sc.nextInt();
}
}
System.out.println(maxProfit(x, products));
}
private static int maxProfit(int x, int[][] products) {
// 根据单位价格可获取的利润排序,如:现在3元,10天后5元,单位价格的利润为(5-3)/3
Arrays.sort(products, (a, b) -> (b[2] - b[1]) * a[1] - (a[2] - a[1]) *b[1]);
// 下标索引代表未花的钱,mem[i]代表此时的能够拥有的最大资金
int[] mem = new int[x + 1];
mem[x] = x; // 一个商品都不买时,最大资金即为原有资金
// recursion with memorization
backtrack(x, products, mem);
int ans = x;
for (int item : mem) {
ans = Math.max(ans, item);
}
return ans;
}
private static void backtrack(int remX, int[][] products, int[] mem) {
for (int[] product : products) {
// 有利润 && 仍可购买 && mem[remX - product[1]]未更新过
// 排序过的数组保证第一次存储的mem[i]即为最优
if (product[1] < product[2] && product[0] > 0 && remX - product[1] >= 0 && mem[remX - product[1]] == 0) {
product[0]--;
mem[remX - product[1]] = mem[remX] + product[2] - product[1];
backtrack(remX - product[1], products, mem);
product[0]++;
}
}
}
}
#include<iostream>
#include<vector>
using namespace std;
int main() {
int bagSize;
cin>>bagSize;
int num;
cin>>num;
vector<int> nums(num);
for (int i = 0; i < num; ++i) {
cin>>nums[i];
}
vector<int> weights(num);
for (int i = 0; i < num; ++i) {
cin>>weights[i];
}
vector<int> values(num);
for (int i = 0; i < num; ++i) {
cin>>values[i];
}
for (int i = 0; i < num; ++i) {
int count = nums[i];
while (count > 1) {
weights.emplace_back(weights[i]);
values.emplace_back(values[i]);
--count;
}
}
vector<int> dp(bagSize + 1, 0);
for (int i = 0; i < weights.size(); ++i) {
for (int j = bagSize; j >= weights[i]; --j) {
dp[j] = max(dp[j], dp[j - weights[i]] + values[i]);
}
}
// for (auto& w : weights) cout << w << ' ';
// cout << endl;
// for (auto& v : values) cout << v << ' ';
// cout << endl;
int i = bagSize;
while (i > 0 && dp[i] == dp[i - 1]) {
--i;
}
int res = dp[i] + bagSize - i;
cout << res << endl;
return 0;
} 转化为0-1背包问题,考虑到一个情况是,如果背包装不满,就是钱没用完的话,总收益等与10天后的收益+之前剩余的钱
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int x = scanner.nextInt();
int m = scanner.nextInt();
int[] lim = new int[m];
int[] a = new int[m];
int[] b = new int[m];
for (int i = 0; i < m; i++)
lim[i] = scanner.nextInt();
for (int i = 0; i < m; i++)
a[i] = scanner.nextInt();
for (int i = 0; i < m; i++)
b[i] = scanner.nextInt();
int[][] dp = new int[m + 1][x + 1];
for (int j = 0; j <= x; j++)
dp[0][j] = j;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= x; j++)
for (int k = 0; k <= Math.min(lim[i - 1], j / a[i - 1]); k++)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * a[i - 1]] + k * b[i - 1]);
System.out.println(dp[m][x]);
}
} my_money = int(input().strip()) class_num = int(input().strip()) num_class = list(map(int, input().strip().split())) price_now = list(map(int, input().strip().split())) price_after = list(map(int, input().strip().split())) price_make = [] for i in range(len(price_now)): price_make.append(price_after[i] - price_now[i]) now_price = [] make_price = [] for i in range(class_num): for j in range(num_class[i]): now_price.append(price_now[i]) make_price.append(price_make[i]) dp = [[0 for i in range(my_money+1)] for i in range(len(now_price))] for j in range(1, my_money+1): if j >= now_price[0]: dp[0][j] = make_price[0] for i in range(len(now_price)): for j in range(1, my_money+1): if now_price[i] > j: dp[i][j] = dp[i-1][j] else: dp[i][j] = max(dp[i-1][j], dp[i-1][j - now_price[i]] + make_price[i]) print(my_money+dp[-1][-1])
多重背包问题,展开为0-1背包问题
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
atoi := func(x []string) []int {
t := []int{}
for _, val := range x {
if val==""{
continue
}
tmp, _ := strconv.Atoi(val)
t = append(t, tmp)
}
return t
}
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
x, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
m, _ := strconv.Atoi(scanner.Text())
scanner.Scan()
xg := atoi(strings.Split(scanner.Text(), " "))
scanner.Scan()
curPrice := atoi(strings.Split(scanner.Text(), " "))
scanner.Scan()
futurePrice := atoi(strings.Split(scanner.Text(), " "))
ans := MySolution(x, m, xg, curPrice, futurePrice)
fmt.Println(ans)
}
func MySolution(x, m int, xg []int, curPrice []int, futurePrice []int) int {
// 本题是多重背包问题
// 将多重背包问题展开为0-1背包问题
for i := 0; i < m; i++ {
count := xg[i]
for count > 1 {
curPrice = append(curPrice, curPrice[i])
futurePrice = append(futurePrice, futurePrice[i])
count--
}
}
max := func(a, b int) int {
if a > b {
return a
}
return b
}
dp := make([]int, x+1) //0-x的下标,表示背包的容量从0-x
for i := 0; i < len(curPrice); i++ {
// 逆序为0-1,正序为完全背包
for j := x; j >= curPrice[i]; j-- {
dp[j] = max(dp[j], dp[j-curPrice[i]]+futurePrice[i])
}
}
i:=x
for i>0&&dp[i]==dp[i-1]{
i-- //获取用掉的钱
}
return (dp[i]+x-i)
}