C++---Knapsack Model/Greedy---Energy Stone (A daily algorithm 2023.4.10)

Note:
This question is an extended question of "Dynamic Programming-01 Backpack" and "Greedy-Acrobatic Cow" . It is recommended to read and understand these two articles first.

Topic:
The rock monster Duda lives in the magic forest. He collected N pieces of energy stones during lunch and prepared to eat them.
Due to his small mouth, he can only eat one power stone at a time.
The power stone is very hard and it takes a long time to finish eating it.
It takes Si seconds to finish eating the i-th energy stone.
Duda gets energy by eating power stones.

Different power stones may contain different energies.
In addition, power stones will gradually lose their power over time.
The i-th power stone initially contains Ei units of energy and will lose Li units of energy every second.
When Duda starts eating a Pendant, he immediately gains all of the energy contained in that Pendant (regardless of how long it takes to actually consume the Stone).

The energy contained in the power stone is reduced to 0 at most.
What is the maximum amount of energy that Duda can obtain by eating energy stones?

Input Format
The first line contains an integer T, indicating that there are T sets of test data in total.
The first line of each set of data contains an integer N, indicating the number of power stones.
Next N lines, each containing three integers Si, Ei, Li.

Output Format
Output one result for each set of data, and each result occupies one line.
Results are expressed as Case #x:y, where x is the group number (starting from 1) and y is the maximum energy value that can be obtained.

Data range
1≤T≤10,
1≤N≤100,
1≤Si≤100,
1≤Ei≤105,
0≤Li≤105

Example Explanation
In Example #1, there are N=4 gems. One stone-eating sequence that Duda can choose is:
eat the fourth stone. This takes 5 seconds and gives him 80 units of energy.
Eat the second stone. This takes 5 seconds and gives him 5 units of energy (the second stone started with 30 units of energy and lost 25 units of energy after 5 seconds).
Eat the third stone. This takes 100 seconds and gives him 20 units of energy (the third stone starts with 30 units of energy and loses 10 units of energy after 10 seconds).
Eat the first stone. This takes 20 seconds and gives him 0 units of energy (the first stone starts with 10 units of energy and after 110 seconds has lost all energy).
He has gained a total of 105 units of energy, which is the maximum possible, so the answer is 105.

In sample case #2, there are N=3 gems.
No matter which stone Duda chooses to eat, the energy of the remaining two stones will be depleted.
So he should eat the third stone, which gives him 8 units of energy.

In sample case #3, there are N=2 gems. Duda can:
eat the first stone. This takes 12 seconds and gives him 300 units of energy.
Eat the second stone. This takes 5 seconds and gives him 200 units of energy (the second stone doesn't lose any energy over time!). So the answer is 500.

输入:
3
4
20 10 1
5 30 5
100 30 1
5 80 60
3
10 4 1000
10 3 1000
10 8 1000
2
12 300 50
5 200 0
输出:
Case 1: 105
Case 2: 8
Case 3: 500
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10010;
int n, m, s, e, l, C;
int f[N];
struct Stone {
    
    
    int s, e, l;
    bool operator<(const Stone &other) const {
    
    return s*other.l < other.s*l;}
} Stone[N];

int main() {
    
    
    cin >> C;
    for (int t = 1; t<=C; t++) {
    
        //处理C组样例
        cin >> n;   //本组样例个数
        m = 0;      //本组样例的总时间
        for (int i = 1; i<=n; i++) {
    
        //读入本组的能量石
            cin >> s >> e >> l;
            Stone[i] = {
    
    s, e, l};
            m += s;
        }
        sort(Stone+1, Stone+n+1);   //贪心,切记+1,因为是从下标1开始读入的不是0
        
        //恰好为j的话初始化除了f[0]都为负无穷即可
        memset(f, -0x3f3f, sizeof f);
        f[0] = 0;
        //一维双循环01背包
        for (int i = 1; i<=n; i++) {
    
    
            s = Stone[i].s; e = Stone[i].e; l = Stone[i].l;
            for (int j = m; j>=s; j--) {
    
    
                f[j] = max(f[j], f[j-s] + e-(j-s)*l);
            }
        }
        int res = 0;
        for (int i = 0; i<=m; i++) res = max(res, f[i]);
        printf("Case %d: %d\n", t, res);
    }
    return 0;
}

Greedy way of thinking:
It is very similar to "greedy-a cow playing acrobatics" . You need to find out the nature of the question and convert it into a formula to be greedy.
Use the same idea to judge the relationship between eating the ifirst energy stone and eating the first ability stone.i+1

1.先吃i再吃i+1: E[i]+E[i+1] - s[i]*L[i+1]
2.先吃i+1再吃i: E[i]+E[i+1] - s[i+1]*L[i]
(前半部分相同,后半部分是计算在吃第一个石头的时候第二个石头损失的能量)

Under what circumstances would 1 be better? That is, when the energy lost by 1 is less than the energy lost by 2, more energy is eaten. That is to say:

s[i]*L[i+1] < s[i+1]*L[i]

Obviously, as long as they are sorted according to this condition, the optimal solution will definitely be to eat i first and then eat i+1.

DP idea:
still the classic y-style dp method.

1. State representation
f[i][j]: For the first i items, all solutions when the volume is exactly j, the attribute is Max.
(Here, "exactly j" is used instead of "not greater than j" because the "j" that depends on the state transition must be an exact time point, not a time period. If it is not greater than j, then the state transition Is it transferred from j-1? Or is it transferred from j-2...jm? There is a problem with the calculation)

2. State calculation
The state calculation is basically the same as the 01 backpack, but the parameters are slightly changed, and the division is still
based on choosing i/not choosing i
: not choosing i: f[i][j] = f[i-1][j]
choosing i: f[i][j] = f[i-1][j-si] + ei-(j-si)*Li
here (js)*Li is calculating the loss energy of.

If it is helpful, please give a free like~ Someone watching is the motivation to support me to write down!

Disclaimer:
The source of the algorithm idea is Mr. Y. For details, please refer to https://www.acwing.com/
This article is only used for learning records and exchanges

Guess you like

Origin blog.csdn.net/SRestia/article/details/130063827