动态规划--输出路径06.25

 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;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值