背包问题再进化--通过装载路径得答案
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了背包问题再进化--通过装载路径得答案相关的知识,希望对你有一定的参考价值。
题目
题目解析
看完题目,可能会懵逼,实际就是选择成本和为target的最大数字。
那么为了让它为最大数字,首先要满足的肯定是位数要够多。所以通过背包模板可以求出成本和为target的最大位数(在背包看来就是物品装入的最大次数)
所以根据以上分析做题可以分为两个步骤:
- 找出和为
target
的最多取数次数(对应最大位数),所以通过背包模板可以求出成本和为target
的最大位数(在背包看来就是物品装入的最大次数)。 - 遍历已经得出结果的
dp
数组,根据它的路径来判断该位数字是否可以取作数位结果,同时为了保证得到的数位是最大情况,需要让数位从大到小的情况来取。 - 对于此题的路径判断方式,如果是直接形式的二维,我们可以通过一个额外的数组来记录每次是否取了物品,若未取则转移到
from[i-1][j]
,若取了则更新答案并转移到from[i][j-coin[i-1]]
。二维如果这样用额外的数组表示,明显会很直观,但额外的空间有点难受。实际上还可以直接用原数组转移:
for(int i=9,j=target;i>=1;i--){
int u = cost[i-1];
//这里如果不满足判断条件,也就是不取第i个物品,则会自动转移到下一个i-1的状态(毕竟外面这层for循环不是盖的。
while (j>=u && dp[i][j]==dp[i](若是01背包则为i-1)[j-u]+1){
//一旦取了第i个物品,则开始更新答案,并判断下一个状态是否还取该物品
ans += to_string(i);
j-=u;
}
}
优化为一维版本:
//由于仅和本行前面的结果相关,即dp[i][j] = dp[i][j-c]故可直接用dp[j-c]代替dp[i][j-c]
for(int i=9,j=target;i>=1;i--){
int u = cost[i-1];
//判断该物品是否被取
while (j>=u && dp[j]==dp[j-u]+1){
//一旦取了第i个物品,则开始更新答案,并判断下一个状态是否还取该物品
ans += to_string(i);
j-=u;
}
}
//如果是01背包我暂时没想出如何在这个回顾路径的过程中优化为一维数组,毕竟他得依赖dp[i-1][j],而一维的只能表示dp[i][j]...
解题代码
只放出了最后的一维解题代码哈。。
效率直接双百:
class Solution {
public:
string largestNumber(vector<int>& cost, int target) {
int dp[target+1];memset(dp,0xf8,sizeof(dp));
//base case:
dp[0] = 0;
for(int i=1;i<= cost.size();i++){
for(int j=cost[i-1];j<=target;j++){
//防止不能拼凑的也被继续拼凑
if(dp[j-cost[i-1]]<0)
continue;
dp[j] = max(dp[j],dp[j-cost[i-1]]+1);
}
}
if(dp[target]==0xf8f8f8f8)return "0";
//开始顺着得到最终结果的路径选择相应的答案
string ans = "";
for (int i = 9, j = target; i >= 1; i--) {
int u = cost[i - 1];
//优先选择数字大的cost[8]开始,以便得到最大值的路径
while (j >= u && dp[j] == dp[j - u] + 1) {
ans += '0'+i;
j -= u;
}
}
return ans;
}
};
以上是关于背包问题再进化--通过装载路径得答案的主要内容,如果未能解决你的问题,请参考以下文章