2 条题解

  • 0
    @ 2025-9-10 12:26:57

    错误题解 您的代码中存在多个严重的语法和逻辑错误,导致它无法编译,也无法正确解决0-1背包问题。我们来逐一分析。

    1. 语法错误 可变长度数组 (VLA): int w[n+1], int v[n+1], int dp[n][c] 这种写法不是标准的C++,虽然某些编译器支持,但不推荐。数组的大小必须是编译时确定的常量。 缺少分号: 在 dp[i][j]=max(...) 这一行的末尾,缺少了一个分号 ;,这会导致编译失败。 未定义的变量: 在最后的输出循环 for(int i=1;i<n;i++){ cout<<dp[i][j]; } 中,变量 j 没有被定义。
    2. 逻辑错误 DP数组大小与索引:

    您的DP数组定义为 dp[n][c],索引从 0 到 n-1 和 0 到 c-1。 但在循环中,您访问了 dp[i-1]。当 i=0 时,这会访问 dp[-1],导致数组越界,程序崩溃。 正确的做法是,DP表的大小应为 dp[n+1][c+1],循环从 i=1 到 n,j=1 到 c。 状态转移方程完全错误:

    情况一:当前容量 j 装不下物品 i (j < w[i]) 您的代码:dp[i][j]=dp[i][j-1]; 这是错误的。 正确逻辑:如果装不下物品 i,那么最大价值应该等于只考虑前 i-1 个物品在同样容量 j 下的最大价值。即 dp[i][j] = dp[i-1][j];。 情况二:当前容量 j 装得下物品 i 您的代码:dp[i][j]=max(dp[i-1][j], dp[i-1][j-1]+v[j]) 这是错误的。 正确逻辑:我们需要在两种选择中取最大值: 不装物品 i:最大价值为 dp[i-1][j]。 装入物品 i:价值为“物品 i 的价值 v[i]”加上“用剩余容量 j - w[i] 去装前 i-1 个物品得到的最大价值 dp[i-1][j - w[i]]”。 所以,正确的转移方程是:dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i]] + v[i]); 输出选择的物品(路径回溯):

    题目要求输出一个01序列表示哪些物品被选中。这需要在计算出最大价值后,从 dp[n][c] 开始回溯DP表来找出决策路径。您的代码完全没有实现这个功能。

    
    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int n;
        cin>>n;
        int w[n+1]={0};
        int v[n+1]={0};
        for(int i=1;i<=n;i++){
            cin>>w[i];
        }
        for(int i=1;i<=n;i++){
            cin>>v[i];
        }
        int c;
        cin>>c;
        int dp[n+1][c+1]={0};
        for(int i=1;i<=n;i++){
            for(int j=1;j<=c;j++){
                if(j<w[i]){
                    dp[i][j]=dp[i-1][j];
                }else{
                    dp[i][j]=max(dp[i-1][j],v[i]+dp[i-1][j-w[i])
                }
            }
        }
        for(int i=1;i<n;i++){
            cout<<dp[i][j];
        }]
        cout<<'\n';
        cout<<dp[n][c];
    }
    
    • 0
      @ 2025-9-10 9:13:56

      C :

      #include <stdio.h>
      #define max 20
      int n,c,w[max],v[max],m[max][max]={0};
      void knapsack()
      {  int i,j;
      for (i=1; i<=n; i++)
      for (j=1; j<=c; j++)
      {   m[i][j]=m[i-1][j];
      if ( j>=w[i-1] && m[i-1][j-w[i-1]]+v[i-1]> m[i][j] ) 
      m[i][j]=m[i-1][j-w[i-1]]+v[i-1];
      }
      }
      void disp( )
      {	int i,j;
      int x[max]={0};
      i=n;
      while ( m[i][c]==m[i-1][c] ) i--;
      while (i>1)
      {	j=i-1;
      while (m[i][c]-m[j][c]!=v[i-1] && j>0)
      j--;
      x[i]=1;
      i=j;
      }
      for(i=2;i<=n;i++)
      printf("%d",x[i]);
      }
      int main( )
      {	int i,j;
       scanf("%d",&n);
      for (i=0; i<n; i++)
      scanf("%d",&v[i]);
      for (i=0; i<n; i++)
      scanf("%d",&w[i]);
      scanf("%d",&c);  
      knapsack();   
      disp();
       printf("\n");
      printf("%d\n",m[n][c]);
       return 0;
      }
      
      

      C++ :

      #include<iostream>
      using namespace std;
      int V[200][200];
      int max(int a,int b)
      {
         if(a>=b)
             return a;
         else return b;
      }
      
      int p(int n,int w[],int v[],int x[],int C)
      {
          int i,j;
          for(i=0;i<=n;i++)
              V[i][0]=0;
          for(j=0;j<=C;j++)
              V[0][j]=0;
          for(i=0;i<=n-1;i++)
      		for(j=0;j<=C;j++)
                  if(j<w[i])
                      V[i][j]=V[i-1][j];
                  else
                      V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]);
                  j=C;
                  for(i=n-1;i>=0;i--)
                  {
                      if(V[i][j]>V[i-1][j])
                      {
                      x[i]=1;
                      j=j-w[i];
                      }
                  else
                      x[i]=0;
                  }
                  for(i=1;i<n;i++)
                  {
      				cout<<x[i];
      			}
      				cout<<"\n";
              return V[n-1][C];
              
      }
      
      int main()
      {
          int s;
          int w[15];
          int v[15];
          int x[15];
          int n,i;
          int C;
          n=5;
          cin>>n;
          for(i=0;i<n;i++)
              cin>>v[i];
          for(i=0;i<n;i++)
      		cin>>w[i];
      	cin>>C;
          s=p(n,w,v,x,C);
      	cout<<s<<"\n";
      }
      

      Java :

      
      import java.util.Scanner;
      
      //本程序取自王晓东编著“算法分析与设计”第 92 页,例
      //0-1背包问题动态规划解法
      class Math {
      
          public Math() {
          }
      
          static int min(int i, int j) {
              if (i > j) {
                  return j;
              } else {
                  return i;
              }
          }
      
          static int max(int i, int j) {
              if (i > j) {
                  return i;
              } else {
                  return j;
              }
          }
      }
      
      public class Main {
      
          public static void knapsack(int[] v, int[] w, int c, int[][] m) {
              int n = v.length - 1;
              int jMax = Math.min(w[n] - 1, c);
              for (int j = 0; j <= jMax; j++) {
                  m[n][j] = 0;
              }
              for (int j = w[n]; j <= c; j++) {
                  m[n][j] = v[n];
              }
              for (int i = n - 1; i > 1; i--) {
                  jMax = Math.min(w[i] - 1, c);
                  for (int j = 0; j <= jMax; j++) {
                      m[i][j] = m[i + 1][j];
                  }
                  for (int j = w[i]; j <= c; j++) {
                      m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
                  }
              }
              m[1][c] = m[2][c];
              if (c >= w[1]) {
                  m[1][c] = Math.max(m[1][c], m[2][c - w[1]] + v[1]);
              }
          }
      
          public static void traceback(int[][] m, int[] w, int c, int[] x) {
              int n = w.length - 1;
              for (int i = 0; i < n; i++) {
                  if (m[i][c] == m[i + 1][c]) {
                      x[i] = 0;
                  } else {
                      x[i] = 1;
                      c -= w[i];
                  }
              }
              x[n] = (m[n][c] > 0) ? 1 : 0;
          }
      
          public static void main(String args[]) {
              
             // int c1 = 10;
              Scanner sc = new Scanner(System.in);
              int n = sc.nextInt();
              int v1[] = new int[n];//{0,6, 3, 5, 4, 6};
              int w1[] = new int[n];//{0,2, 2, 6, 5, 4};
              for(int i=0;i<n;i++)
              {
                  v1[i]=sc.nextInt();
              }
                for(int i=0;i<n;i++)
              {
                  w1[i]=sc.nextInt();
              }
                int c1 = sc.nextInt();
      //        System.out.print("v1[]={");
      //        for (int i = 0; i < v1.length; i++) {
      //            System.out.print(v1[i]);
      //        }
      //        System.out.print("}");
      //        System.out.println();
      //        System.out.print("w1[]={");
      //        for (int i = 0; i < w1.length; i++) {
      //            System.out.print(w1[i]);
      //        }
      //        System.out.print("}");
      //        System.out.println();
      //        System.out.println("c=" + c1);
              int n1 = v1.length - 1;
              int x1[] = new int[n1 + 1];
              int[][] m1 = new int[n1 + 1][c1 + 1];
              knapsack(v1, w1, c1, m1);
              traceback(m1, w1, c1, x1);
              for (int i = 1; i <= n1; i++) {
      //            if (x1[i] == 1) {
                      System.out.print(x1[i]);
      //            }
              }
              System.out.println();
              System.out.println(m1[1][c1]);
          }
      }
      
      • 1

      信息

      ID
      4230
      时间
      1000ms
      内存
      128MiB
      难度
      10
      标签
      递交数
      1
      已通过
      1
      上传者