题目链接:传送门

       做这道题的时候不知道怎么输出路径,然后我就很麻烦的先用01背包把能装下的最大值求出来,然后用这个最大值去用递归输出路线,很麻烦,然后看了别人的代码,发现可以在更新dp[j]的值的时候记录下当前的dp[i][j]。

先上之前的我写的递归输出路径的代码:

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,num;
int pre[1005];
int dp[1005];
int a[1005];
int flag;

void Output(){
  for(int i=0;i<num;i++)
  printf("%d ",a[i]);
  flag = 1;
  return ;
}

void dfs(int x,int sum){
  if(sum == dp[n]){
    Output();
    return ;
  }
  if(flag == 1)return ;
  if(sum > dp[n])return ;
  for(int i=x;i<m;i++){

    a[num++] = pre[i];
    dfs(i+1,sum+pre[i]);
    if(flag == 1)return ;
    num--;
  }
  return ;
}

int main()
{
  while(~scanf("%d%d",&n,&m)){
    flag = 0;
    for(int i=0;i<m;i++){
      scanf("%d",&pre[i]);
    }
    memset(dp,0,sizeof(dp));
    for(int i=0;i<m;i++){
      for(int j=n;j>=pre[i];j--){
        dp[j] = max(dp[j],dp[j - pre[i]] + pre[i]);
      }
    }
    num = 0;
    dfs(0,0);
    printf("sum:%d\n",dp[n]);
  }
  return 0;
}

然后是简单的标记输出路径代码:

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,num;
int pre[10005];
int dp[10005];
int a[10005][10005];
int flag;

int main()
{
  while(~scanf("%d%d",&n,&m)){
    flag = 0;
    for(int i=0;i<m;i++){
      scanf("%d",&pre[i]);
    }
    memset(a,0,sizeof(a));
    memset(dp,0,sizeof(dp));
    for(int i=m-1;i>=0;i--){
      for(int j=n;j>=pre[i];j--){
        if(dp[j] < dp[j - pre[i]] + pre[i]){
        dp[j] = dp[j - pre[i]] + pre[i];
        a[i][j] = 1;
      }
    }
  }
    for(int i=0,j=n;i<m;i++){
      if(a[i][j]){
        printf("%d ",pre[i]);
        j -= pre[i];
      }
    }
    printf("sum:%d\n",dp[n]);
  }
  return 0;
}