[Knapsack Problem] Greedy Algorithm and Others

Statement

The author is not a professional programmer. This article is just sharing his own experience. If there are many mistakes, please point them out. If you don’t like it, please don’t complain.

This article uses the Pascal language that a novice like the author understands.

This blog is also written for a friend of mine who doesn’t understand code but is very interested in algorithms, so I don’t include some “advanced” elements.

The writing is a bit hasty, please forgive me 😛

This article introducesgreedy algorithm, focusing onpart of the knapsack problem.

This article refers to the detailed explanation of the backpack problem (including code)_Lin 128’s Blog-CSDN Blog

1. Title Description

1.01 Backpack

There are N items and a backpack with capacity V. The space consumed to put the i-th item is Ci, and the value obtained is Wi. Find which items can be packed into a backpack to maximize the total value.

Features: There is only one of each item, you can choose to put it or not. That is, there are two states: 0 (not put) and 1 (put)

2. Partial Backpack

There are N items and a backpack with capacity V. The space consumed to put the i-th item is Ci, the value obtained is Wi, and the item can be divided. Find which items can be packed into a backpack to maximize the total value.

Features: Items can be divided

3. Complete Backpack

There are N kinds of items and a backpack with a capacity V. There are unlimited pieces of each item available. The cost of putting the i-th item is Ci and the value is Wi. Solution: Which items can be put into the backpack so that the total cost of these items does not exceed the backpack capacity and the total value is the largest.

Features: Each item can be used unlimitedly

4.Multiple backpacks

There are N kinds of items and a backpack with capacity V. There are at most Mi items available for the i-th item, the space consumed by each item is Ci, and the value is Wi. Find out which items can be packed into the backpack so that the total space consumed by these items does not exceed the capacity of the backpack and the total value is the largest.

Features: The quantity of each item is different

5. Other backpacks…

Group backpacks, Associated backpacks…and those backpack problems that don’t look like backpack problems

Lecture 1 01 Backpack Problem

This is the most basic backpack problem. Each item can only be placed at most once.

Lecture 2 Complete Knapsack Problem

The second basic knapsack problem model, each item can be placed an infinite number of times.

Lecture 3 Multiple Knapsack Problem

Each item has a fixed maximum number of uses.

Lecture 4: Mixing Three Kinds of Knapsack Problems

Superimpose the previous three simple problems into more complex problems.

Lecture 5: Knapsack problem with two-dimensional costs

A simple common extension.

Lecture 6: Grouped Knapsack Problem

A question type that is also a useful model. The basis for the next two sections.

Lecture 7: Dependent Knapsack Problem

Another way to put restrictions on item selection.

Lecture 8 Generalized Items

The results of my own thinking about the backpack problem are a bit abstract.

Lecture 9: Changes in how to ask the knapsack problem

Try to draw inferences and draw inferences.

———————————-

forward from

xiaoyao_zhang

2. Question analysis

1. Partial Knapsack & Greedy Algorithm

Starting with the features, items can be divided, which means we don’t have to worry about not filling up the backpack. During the segmentation process, grasp the constant quantity, such as – Cost-performance ratio, that is, Wi/Ci, which represents the value of unit weight. So how to release it? Since you don’t have to worry about wasted space or unreasonable arrangements, just sort all the items in descending order of cost-effectiveness and put them into the backpack one by one. When it cannot fit, divide the current items and fill up the remaining space.

①. Greedy algorithm

In this idea, we ensure that every time we put in the items that are currently the most cost-effective, the total value is the greatest. This is the greedy algorithm. The greedy algorithm, as its name suggests, does not consider possible future branches, but focuses on the optimal solution to the current sub-problem. I want the best, no matter if there is something better, it’s that simple.

②. Learn and apply in a practical way

There is such an optimal loading problem: there are N items and a backpack with a capacity of V. The space consumed to put the i-th item is Ci, and each item is equivalent. Find which items can be packed into a backpack to maximize the total value. (Indivisible)

The items here are equivalent, that is to say, Wi/Ci=1/Ci, so the smaller the item, the more cost-effective. Therefore, we can get the following greedy idea: Sort the items in order of space from small to large, and start loading the small ones first. , until the remaining space is insufficient.

2.01 Backpack

Next, let’s go through them in order.

For situations that cannot be divided, the short-sighted greedy algorithm is no longer applicable, and the brute force algorithm of exhaustive calculation will cause the time to exceed the limit. So how to optimize? Infinite enumeration is a kind of search, and optimized search can be done by retaining the historical optimal solution – huh? Dynamic programming!

For details on dynamic programming, please see my [[NOIP1999 Popularization Group] Missile Interception – Longest Non-Ascending Subsequence Problem] Dynamic Planning – CSDN blog article has been read 136 times. The first time I tried dynamic programming dp, I started from the example problem to think hard. The embodiment of mathematical induction in Coding (personal opinion) https://blog.csdn.net/MPCBexplorer/article/details/133953631

The dynamic transfer equation here is:

dp[i,v]=max(dp[i,v],dp[i?1,v?Ci] + Wi)

Translate: dp[i,v] stores the sub-problem of putting the first i items into a backpack with capacity v. The initial value of dp[i,v] is dp[i-1,v], which is the maximum value after selecting the first i-1 items. When faced with the choice of the i-th item and the current backpack capacity is v, choose 1. If you do not choose this item, the current maximum value is the maximum value after the last judgment and 2. When you select this item, the current value is the maximum value of the remaining capacity distance when the remaining capacity is exactly Ci plus the value of this item after the last selection.

Finally, output dp[N,V]. It is not difficult to conclude that as long as the item information is determined, the answers to all V cases can be obtained through this equation, and finally V output is selected as needed.

3. Complete backpack & multiple backpacks

I only provide one idea here. For other ideas, please refer to the great article (link at the beginning)

All problems are transformed into mathematical problems, all mathematical problems are transformed into algebraic problems, and all algebraic problems are transformed into equation problems – Descartes

All knapsack problems (except some knapsacks) are converted into 01 knapsack problems, and all 01 knapsack problems are converted into dynamic programming problems – MPCBexplorer

For a complete backpack, it can be considered as a 01 backpack that is filled with capacity j and contains at most V/ci items of weight wi, that is, the quantity k <= j/wi. The purpose is achieved by traversing k based on the item selection loop and weight traversal loop.

dp[i][j] = max(dp[i][j],dp[i-1][j-kci] + kwi), 0<=k<=j/ci

Regarding multiple backpacks, the boss has two ideas, one is directly transformed into an 01 backpack, and the other is indirectly transformed into a 01 backpack through a complete backpack. Personally I think the latter is easier to understand.

A complete backpack, isn’t it just a 01 backpack with quantity? Although the number is unlimited, there must be 0<=k<=j/wi, and k actually has a range; the same is true for multiple backpacks, but there are two situations: 1. When the remaining space is enough, 0<=k<=mi ; 2. When there are enough items, 0<=k<=j/wi - you see, there is just one more condition for the upper limit of taking items with enough space! When deciding specifically which one is the upper limit in the program, take

Ki=min(num[i],j/ci)

That’s it, and then there’s the complete backpack idea above:dp[i][j] = max(dp[i][j],dp[i-1][j-kci] + kwi)< /strong>

3. Upload the code

1. Part of the backpack

program part_bag;
var
        n,i:longint;
        v,ans:real;
        a,c,w:array[1..10000] of real;
// Sort by cost performance
//Steal a quick change in the system file
//Quick sort: a sort based on binary search method
procedure sort(l,r: longint);
      var
         i,j: longint;
         x,y:real;
      begin
         i:=l;
         j:=r;
         x:=a[(l + r) div 2];
         repeat
           while a[i]<x do
            inc(i);
           while x<a[j] do
            dec(j);
           if not(i>j) then
             begin
                y:=a[i];
                a[i]:=a[j];
                a[j]:=y;
                y:=c[i];
                c[i]:=c[j];
                c[j]:=y;
                y:=w[i];
                w[i]:=w[j];
                w[j]:=y;
                inc(i);
                j:=j-1;
             end;
         until i>j;
         if l<j then
           sort(l,j);
         if i<r then
           sort(i,r);
      end;
begin
        //Quantity, size
        read(n,v);
        for i:=1 to n do
                begin
                        // size, value
                        read(c[i],w[i]);
                        //price/performance ratio
                        a[i]:=w[i]/c[i];
                end;
        sort(1,n);
        //DEBUG debugging: cost-effectiveness after output sorting
        //for i:=1 to n do writeln(a[i]:0:2);
        i:=n;
        //When there is enough space
        while v>=c[i] do
                begin
                        //Greedy: load all
                        ans:=ans + w[i];
                        v:=v-c[i];
                        dec(i);
                end;
        //Split the last item
        ans:=ans + w[i]*(v/c[i]);
        writeln(ans:0:2);
end.

Enter #1

4 50↙

10 60↙

20 100↙

30 120↙

15 45↙

Output #1

240.00

2.01 Backpack

program o1_bag;
var
        n,v,i,j,best:longint;
        c,w:array[1..10000] of longint;
        //Note that the subscript starts from 0
        dp:array[0..10000,0..10000] of longint;
//Function to get the maximum value
function max(a,b:longint):longint;
        begin
                if a>b then exit(a)
                       else exit(b);
        end;
begin
        read(n,v);
        for i:=1 to n do read(c[i],w[i]);
        //i: in the first i items
        for i:=1 to n do
                //j: When the remaining capacity is j
                for j:=0 to v do
                        begin
                                //No matter whether the remaining space is enough or not, at least there is
                                dp[i,j]:=dp[i-1,j];
                                //When there is enough remaining space
                                if j>=c[i] then dp[i,j]:=max(dp[i-1,j-c[i]] + w[i],dp[i,j]);
                        end;
        best:=0;
        //Find the maximum value output
        for j:=1 to v do
                if dp[n,j]>best then best:=dp[n,j];
        writeln(best);
end.

Enter #1

4 5

1 2↙

2 4↙

3 4↙

4 5↙

Output #1

8

3. Complete backpack

program completed_bag;
var
        n,v,i,j,k,best:longint;
        c,w:array[1..10000] of longint;
        //Note that the subscript starts from 0
        dp:array[0..10000,0..10000] of longint;
//Function to get the maximum value
function max(a,b:longint):longint;
        begin
                if a>b then exit(a)
                       else exit(b);
        end;
begin
        read(n,v);
        for i:=1 to n do read(c[i],w[i]);
        //i: in the first i items
        for i:=1 to n do
                //j: When the remaining capacity is j
                for j:=0 to v do
                        begin
                                //No matter whether the remaining space is enough or not, at least there is
                                dp[i,j]:=dp[i-1,j];
                                for k:=0 to j div c[i] do
                                        //When there is enough remaining space
                                        if j>=k*c[i] then dp[i,j]:=max(dp[i-1,j-k*c[i]] + k*w[i],dp[i,j]);
                        end;
        best:=0;
        //Find the maximum value output
        for j:=1 to v do
                if dp[n,j]>best then best:=dp[n,j];
        writeln(best);
end.

Enter #1

4 5

1 2↙

2 4↙

3 4↙

4 5↙

Output #1

10

4. Multiple backpacks

program numbers_of_bags;
var
        n,v,i,j,k,best:longint;
        c,w,m:array[1..10000] of longint;
        //Note that the subscript starts from 0
        dp:array[0..10000,0..10000] of longint;
//Function to get the maximum value
function max(a,b:longint):longint;
        begin
                if a>b then exit(a)
                       else exit(b);
        end;
//Function to get the minimum value
function min(a,b:longint):longint;
        begin
                if a<b then exit(a)
                       else exit(b);
        end;
begin
        read(n,v);
        for i:=1 to n do read(c[i],w[i],m[i]);
        //i: in the first i items
        for i:=1 to n do
                //j: When the remaining capacity is j
                for j:=0 to v do
                        begin
                                //No matter whether the remaining space is enough or not, at least there is
                                dp[i,j]:=dp[i-1,j];
                                for k:=0 to min(m[i],j div c[i]) do
                                        //When there is enough remaining space
                                        if j>=k*c[i] then dp[i,j]:=max(dp[i-1,j-k*c[i]] + k*w[i],dp[i,j]);
                        end;
        best:=0;
        //Find the maximum value output
        for j:=1 to v do
                if dp[n,j]>best then best:=dp[n,j];
        writeln(best);
end.

Enter #1

3 7↙

2 3 12↙

2 5 15↙

1 2 3↙

Output #1

17

4. Conclusion

When explaining the greedy algorithm from the perspective of the knapsack problem, I didn’t expect that the protagonist turned out to be dynamic programming. Greedy is an entry-level algorithm that should be mastered; however, it will not appear frequently in the future. After all, dynamic programming is the king, and greed is always easy to miss the optimal solution.

The poem says:

The screen is filled with absurd words and a handful of bitter tears.

They are all crazy about coders, who can explain their hatred!

If there are any bugs in the code, please point them out, thank you!

I’m so exhausted! Finished the first draft at 23:31!

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Algorithm skill tree Home page Overview 57530 people are learning the system

syntaxbug.com © 2021 All Rights Reserved.