01 knapsack problem-dynamic programming

Problem Description

There are n items, and they have their own volume and value. With a backpack with a given capacity, how to make the items in the backpack have the largest sum of value?

For example, if there are 4 items, the maximum capacity (bagv) of the backpack can be 8, and the item's capacity and value are 2 3, 3 4, 4 5, 5 6 and
use w to represent the capacity of the item, and v to represent the item’s capacity. The value is as follows:

i (item number) 1 2 3 4
w (item capacity) 2 3 4 5
v (item value) 3 4 5 6

The core of dynamic programming is to fill in the table. Many data only need to be calculated once and saved in the table, so efficiency can be improved.
To determine whether the i-th item can be put down, one has to consider whether j (the current backpack state) at this time is greater than w(i).
Find the recurrence relation

  • If j<=w(i) (can't put it down): At this time, the current state is the previous state dp[i][j]=dp[i-1][j]
  • If j>=w(i) (can be put down): At this time, it is necessary to consider the best choice of the two choices of keeping the item.
    (1) If not released, dp[i][j]=dp[i-1][j]
    (2) If released, dp[i][j]=dp[i-1][jw[i]] +v[i]
    should be: max(dp[i][j]=dp[i-1][j],dp[i][j]=dp[i-1][jw[i]] +v[i])
    With such thoughts and relations, you can write the code and implement the
    code
#include <iostream>
using namespace std;
int main()
{
    
    
int maxn=0,n,bagv,i,j,w[500],v[500],dp[20][20]={
    
    {
    
    0}};
 cin>>n>>bagv;
 for(i=1;i<=n;i++)
 {
    
    
  cin>>w[i]>>v[i];
 }
 for(i=1;i<=n;i++)
 {
    
    
  for(j=1;j<=bagv;j++)
  {
    
    
   if(w[i]>j)
   {
    
    
    dp[i][j]=dp[i-1][j];
   }
   else {
    
    
    dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]);
    if(dp[i][j]>maxn)
    {
    
    
     maxn=dp[i][j];
    }
   }
  }
 }
 for(i=0;i<=n;i++)
 {
    
    
  for(j=0;j<=bagv;j++)
  cout<<dp[i][j]<<" ";//打印表格
  cout<<endl;
 }
cout<<maxn<<endl;
return 0;
}

Backtracking of the optimal solution of the knapsack problem
If you want to know what is placed under the optimal conditions in a specific knapsack, you can use backtracking and reverse search and judgment through the same recurrence relationship.

  • If dp[i][j]==dp[i-1][j] , that is, the i-th one is not put in the backpack, then go to the previous one (i-1)
  • If dp[i][j]==dp[i-1][jw[i]]+v[i] , that is, the i-th is put in the backpack, mark the i at this time, and then check the previous (i -1)
    All are judged until i=1

Code

#include <iostream>
using namespace std;
int item[20]={
    
    0};
int maxn=0,n,bagv,i,j,w[500],v[500],dp[20][20]={
    
    {
    
    0}};
void findwhat(int i,int j)
{
    
    
 if(i>=1)
 {
    
    
  if(dp[i][j]==dp[i-1][j])//判断i放了没
  {
    
    
   item[i]=0;
   findwhat(i-1,j);
  }
  else if(j>=w[i]&&dp[i][j]==dp[i-1][j-w[i]]+v[i])
  {
    
    
   item[i]=1;
   findwhat(i-1,j-w[i]);
  }
 }
}
int main()
{
    
    
 cin>>n>>bagv;
 for(i=1;i<=n;i++)
 {
    
    
  cin>>w[i]>>v[i];
 }
 for(i=1;i<=n;i++)
 {
    
    
  for(j=1;j<=bagv;j++)
  {
    
    
   if(w[i]>j)
   {
    
    
    dp[i][j]=dp[i-1][j];
   }
   else {
    
    
    dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]);
    if(dp[i][j]>maxn)
    {
    
    
     maxn=dp[i][j];
    }
   }
  }
 }
 for(i=0;i<=n;i++)
 {
    
    
  for(j=0;j<=bagv;j++)
  cout<<dp[i][j]<<" ";
  cout<<endl;
 }
 cout<<maxn<<endl;
 findwhat(n,bagv);
 for(i=1;i<=n;i++)
  if(item[i]==1)
  cout<<i<<" ";
 cout<<endl;
 return 0;
}

Guess you like

Origin blog.csdn.net/HT24k/article/details/105816968