https://www.cnblogs.com/jbelial/articles/2116074.html
博客参考
https://www.cnblogs.com/jbelial/articles/2116074.html
12. 背包问题求具体方案 - AcWing题库
由于需要求解最小字典序,尝试输入数据时逆序输入,其他不改变,状态含义不变,如下,10/11
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010,INF=1e9;
int f[N][N],v[N],w[N];
int path[N];
int n,m;
int ans;
int main(){
cin>>n>>m;
f[0][0]=0;
for(int i = n;i >= 1;i--)cin>>v[i]>>w[i],f[0][i]=-INF;
for(int i = 1;i <= n;i++)
for(int j = 0; j <= m ;j++){
f[i][j]=f[i-1][j];
if(j>=v[i])
f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
}
ans=0;
int tmp;
for(int i = 1;i <= m;i++){
if(ans<f[n][i])ans=f[n][i],tmp=i;
}
/*
cout<<tmp<<endl;
for(int i = 1; i<= n;i++){
for(int j = 0;j<=m;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
*/
for(int i = n;i >= 1;i--){
if(tmp-v[i] >= 0 && f[i][tmp]==f[i-1][tmp-v[i]]+w[i]){
path[i]=1;
tmp-=v[i];
}
}
for(int i = n;i >= 1;i--){
if(path[i]==1)cout<<n+1-i<<" ";
}
return 0;
}
f[i][j]表示前i个物品,重为j时的最大价值。
如何输出路径,并且保证是最小字典序,AcWing 12. 背包问题求具体方案状态表示的解释 - AcWing
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010,INF=1e9;
int f[N][N],v[N],w[N];
int n,m;
//f[i][j]表示从第i个物品开始到第n个物品选择,重不超过j的所有方案对应价值最大值
//f[i][j]=max(f[i+1][j],f[i+1][j-v[i]]+w[i])
//f[n+1][j]=0,j=0,1,2,3...,m;
int main(){
cin>>n>>m;
for(int i = 1;i <= n;i++)cin>>v[i]>>w[i];
for(int i = n;i >= 1;i--)
for(int j = 0; j <= m ;j++){
f[i][j]=f[i+1][j];
if(j>=v[i])
f[i][j]=max(f[i+1][j],f[i+1][j-v[i]]+w[i]);
}
/*for(int i = 1; i<=n;i++)
{
for(int j = 1; j<= m;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
*/
for(int i = 1;i <= n;i++){//从小到大枚举
//cout<<"m="<<m<<endl;
if(m-v[i]>=0&&f[i][m]==f[i+1][m-v[i]]+w[i]){// 能选择就选择
//cout<<"m="<<m<<endl;
cout<<i<<" ";
m-=v[i];
//cout<<"m="<<m<<endl;
}
}
return 0;
}
1449. 数位成本和为目标值的最大数字
力扣
C++第一版
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 110,INF=1e9;
//4 3 2 5 6 7 2 5 5
//9
//7 6 5 5 5 6 8 7 8
//12
//2 4 6 2 4 6 4 4 4
//5
//6 10 15 40 40 40 40 40 40
//47
//f[i][j],选择前i个物品,重量是j时的所有方案的最大价值
int f[N][N];
int v[N],w[N];
int m;
int main(){
f[0][0]=0;
for(int i = 1;i <= 9;i++){
cin>>v[i];
w[i]=1;
}
cin>>m;
//cout<<0<<" ";
for(int i = 1;i <= m;i++){
f[0][i]=-INF;
//cout<<i<<" ";
}
//cout<<endl;
for(int i = 1; i<= 9;i++){
for(int j = 0; j <= m;j++){
f[i][j]=f[i-1][j];
if(v[i]<=j)
f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
//for(int k = 1; k*v[i]<=j;k++)
// f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
//cout<<f[i][j]<<" ";
}
//cout<<endl;
}
/*
cout<<"finally"<<endl;
for(int i = 1;i <= 9;i++){
for(int j = 0; j <= m;j++)
cout<<f[i][j]<<" ";
cout<<endl;
}
*/
string ans;
int j = m;
if(f[9][m]<0)cout<<'"'<<"0"<<'"'<<endl;
else{
//cout<<'"';
for(int i = 9; i >= 1;i--){
for(int c = v[i]; j>=c && f[i][j]==f[i][j-c]+w[i];j-=c)
{
//cout<<i;
ans.push_back(i+'0');
//没有选则v[i]
}
}
//cout<<'"';
}
cout<<'"';
cout<<ans;
cout<<'"';
return 0;
}
C++第二版
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 110,INF=1e9;
//4 3 2 5 6 7 2 5 5
//9
//7 6 5 5 5 6 8 7 8
//12
//2 4 6 2 4 6 4 4 4
//5
//6 10 15 40 40 40 40 40 40
//47
//f[i][j],选择前i个物品,重量是j时的所有方案的最大价值
int f[N];
int v[N],w[N];
int m;
int main(){
f[0]=0;
for(int i = 1;i <= 9;i++){
cin>>v[i];
w[i]=1;
}
cin>>m;
for(int i = 1;i <= m;i++){
f[i]=-INF;
}
for(int i = 1; i<= 9;i++)
for(int j = 0; j <= m;j++){
if(v[i]<=j)
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
string ans;
int j = m;
if(f[m]<0)cout<<'"'<<"0"<<'"'<<endl;
else{
for(int i = 9; i >= 1;i--){
for(int c = v[i]; j>=c && f[j]==f[j-c]+w[i];j-=c)
{
ans.push_back(i+'0');
//没有选则v[i]
}
}
}
cout<<'"';
cout<<ans;
cout<<'"';
return 0;
}
leedcode提交:
class Solution {
public:
string largestNumber(vector<int>& cost, int target) {
//f[i][j],选择前i个物品,重量是j时的所有方案的最大价值
int f[5050];
f[0]=0;
for(int i = 1;i <= target;i++){
f[i]=-1000000000;
}
for(int i = 1; i<= 9;i++){
for(int j = 0; j <= target;j++){
if(j-cost[i-1]>=0)//多重背包问题
f[j]=max(f[j],f[j-cost[i-1]]+1);
}
}
string ans;//记录路径
int j = target;//输出路径
if(f[target]<0)ans.push_back('0');//小于0,没有满足题意的方案
else{
for(int i = 9; i >= 1;i--){//枚举
for(int c = cost[i-1]; j>=c && f[j]==f[j-c]+1;j-=c)//f[i][j]=f[i-1][j],f[i-1][j-v[i]]+1
{
ans.push_back(i+'0');
//选择v[i] ,f[i][j]=f[i-1][j-v[i]]+1
}
}
}
return ans;
}
};