原文地址:https://blog.csdn.net/ronaldo7_zyb/article/details/81069906

1. 要求输出方案:

以01背包为例

我们可以知到,01背包用一维数组表示的状态转移方程是:
f[j]=max(f[j],f[j−vi]+wi)f[j]=max(f[j],f[j−vi]+wi)f[j]=max(f[j],f[j−vi]+wi)

那么,要求输出方案时应该怎么办呢?我们没有在决策过程中记录方案,按照动态规划的过程方案并非固定,因此我们需要通过动态规划的结果来得出其中之一的选择方案.
根据状态转移方程,若f[j]=f[j−v1]+wif[j]=f[j-v1]+wif[j]=f[j−v1]+wi,则说明这件物品是选择的.因此我们根据这一结论,通过对结果的不断相减的处理以及判断,便可以得到期中之一的方案.

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,V,t=0;
int v[10000];
int w[10000];
int ans[1000];
int f[2000][2000];
int main()
{ios::sync_with_stdio(false); cin>>n>>V;for (int i=1;i<=n;i++)cin>>v[i]>>w[i];for (int i=1;i<=n;i++)for (int j=0;j<=V;j++){if (j<v[i]) f[i][j]=f[i-1][j];else f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);}while (n>0&&V>0){if (f[n][V]==f[n-1][V-v[n]]+w[n]){ans[++t]=n;V=V-v[n];}n--;}for (int i=t;i>=1;i--)cout<<ans[i]<<' ';return 0;
}

2.求字典序最小的方案数:

以01背包为例
我们知道,按照上述程序的方法,一定无法保证字典序最小,即:
如果要保证字典序是最小的,必然要在从小到达枚举选择策略的时,若枚举到的物品可选可不选的时候,必然是要选的,例如枚举到了1-4,若一号物品可选可不选的时候,必然要选,毕竟以1开头无论如何字典序都是最大的;按上述策略,是从n-1枚举的,显然如果先选n便必然不能保证字典序的最小.因此,我们需要调换一下顺序,即读入的时候将for循环倒序读入,在输出n的时候再以输出n-i+1就能够保证序列顺序和答案的正确性.
代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,V,t=0,N;
int v[10000];
int w[10000];
int ans[1000];
int f[2000][2000];
int main()
{ios::sync_with_stdio(false); cin>>N>>V;n=N;for (int i=n;i>=1;i--)cin>>v[i]>>w[i];for (int i=1;i<=n;i++)for (int j=0;j<=V;j++){if (j<v[i]) f[i][j]=f[i-1][j];else f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);}while (n>0&&V>0){if (f[n][V]==f[n-1][V-v[n]]+w[n]){cout<<N-n+1<<' ';V=V-v[n];}n--;}return 0;
}

3.可行方案总数:以01背包为例

我们知道,若以价值而论,状态转移方程便是:
f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)

其中的状态转移方程f[i][j]f[i][j]f[i][j]表示前i件物品与容量为j的背包物品的最大价值;那么我们在面对这个相同条件但所求结果不同的问题中,我们便可以设f[i][j]f[i][j]f[i][j]为前i件物品组合出来的容量为j的方案数,因此,我们同样可以分两种情况进行讨论来得出状态转移方程,即我们枚举i和j的时候:
取:方案数为f[i−1][j]f[i-1][j]f[i−1][j] 2.不取:方案数为f[i−1][j−vi]f[i-1][j-vi]f[i−1][j−vi] 故状态转移方程如下(sum表示累加):
f[i][j]=sum(f[i−1][j],f[i−1][j−vi])f[i][j]=sum(f[i−1][j],f[i−1][j−vi])f[i][j]=sum(f[i−1][j],f[i−1][j−vi])

优化成一维,便是:
f[j]=sum(f[j],f[j−vi])f[j]=sum(f[j],f[j−vi])f[j]=sum(f[j],f[j−vi])

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,V,ans=0;
int v[100000];
int f[100000];
int main()
{ios::sync_with_stdio(false);cin>>n>>V;for (int i=1;i<=n;i++)cin>>v[i];f[0]=1;for (int i=1;i<=n;i++)for (int j=V;j>=v[i];j--)f[j]+=f[j-v[i]];for (int i=1;i<=V;i++)if (f[i]>=1) ans++;cout<<f[n]<<' '<<ans;//f[n]表示拼成大小n的方案总数;ans表示能拼成的数子总量return 0;
}

4.最优方案总数:以01背包为例

设f[i][j]f[i][j]f[i][j]表示前i件物品容量为j的最大价值,g[i][j]g[i][j]g[i][j]为该f[i][j]f[i][j]f[i][j]状态最优方案的方案总数
根据状态转移方程:
f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)f[i][j]=max(f[i−1][j],f[i−1][j−vi]+wi)

可以知道,g[i][j]g[i][j]g[i][j]的方案数同样是通过g[i][j]g[i][j]g[i][j]的决策情况来知道的.因此我们可以简单地退出g[i][j]的状态转移方程:

如果我们优化成一维,g[i]的原先状态本来就累加在本身,则方程是:

代码如下(请不要忽略注释的内容):

#include<bits/stdc++.h>
using namespace std;
int n,V;
int f[100000];
int g[100000];
int v[100000];
int w[100000];
int main()
{ios::sync_with_stdio(false);cin>>n>>V;for (int i=1;i<=n;i++)cin>>v[i]>>w[i];g[0]=1;for (int i=1;i<=n;i++)for (int j=V;j>=v[i];j--){//if (f[j]>f[j-v[i]]+w[i]) g[i]和f[i]的值都不变 if (f[j]==f[j-v[i]]+w[i]) g[j]+=g[j-v[i]];//f[j]的值保持不变 if (f[j]<f[j-v[i]]+w[i]) g[j]=g[j-v[i]],f[j]=f[j-v[i]]+w[i]; }//以上3个if语句为3种注释的情况cout<<g[V];return 0;
}

背包问题 输出方案、输出字典序最小方案、可行方案数、最优方案总数相关推荐

  1. hihoCoder #1468 : 2-SAT·hihoCoder新春晚会(2-SAT 输出字典序最小的方案)

    描述 hihoCoder新春晚会正在紧张地筹备中.晚会分为上半场和下半场,总导演小Hi现在要为N个节目安排演出时间(上半场或下半场).为了描述方便,我们将第i个节目对应两个编号2i-1和2i,分别表示 ...

  2. Unidirectional TSP UVA - 116(多阶段决策+输出字典序最小的路径)

    Unidirectional TSP UVA - 116 题意: 给你m行n列的矩阵,从第一列出发,到最后一列. 要求 经过的整数和最小. 输出路径上,每列的行号,多解时,输出字典序最小的. 思路: ...

  3. UVA116 单向TSP Unidirectional TSP(多阶段决策问题、输出字典序最小的方案、DAG上DP)

    整理的算法模板合集: ACM模板 题目传送门 简单的多阶段决策问题. 多段图DAG,其节点可以划分为若干个阶段,每一个阶段只由上一个阶段所决定. 因为本题要求输出从前到后的方案,所以我们转移方程的时候 ...

  4. UVA10537 The Toll! Revisited (思维、最短路、输出字典序最小路径)

    整理的算法模板合集: ACM模板 题目链接 我们要注意去的时候交的n/20单位的货物,但是倒着回去求答案的时候我们要加上ceil(n/19.0)(自己手算) 字典序中大写字母比小写字母更小 注意看数据 ...

  5. poj 1041(欧拉回路+输出字典序最小路径)

    题目链接:http://poj.org/problem?id=1041 思路:懒得写了,直接copy吧:对于一个图可以从一个顶点沿着边走下去,每个边只走一次,所有的边都经过后回到原点的路.一个无向图存 ...

  6. poj 1815 Friendship 最小割 拆点 输出字典序

    题目链接:http://poj.org/problem?id=1815 题意:A与B能通信当且仅当A知道B的电话号或者A知道C的电话号且C与B能通信.若A知道B的电话号,那么B也知道A的电话号. 然而 ...

  7. hdu 1814 字典序最小的2sat(暴力深搜)

    题意:      题意就是最基础的2sat,关系只有矛盾关系,然后二选一,关键是这个题目是输出字典序最小的那组解. 思路:      输出字典序最小,用强连通那个实现不了(起码没看到有人实现),其实我 ...

  8. tomcat调优方案

    前段时间参加面试,面试过程中提到服务器的调优方案,这里总结一下. 首先说一下tomcat的调优方案: Tomcat本身的优化,Java虚拟机调优,Tomcat 优化分为系统优化,接下来一个个介绍: 一 ...

  9. ChatGPT做PPT方案,10组提示词方案!

    今天我们要搞定的PPT内容是: 活动类型:节日活动.会员活动.新品活动 分析类型:用户分析.新品立项.项目汇报 内容类型:内容规划.品牌策划 用到的工具: mindshow 邀请码   6509097 ...

最新文章

  1. nodejs图片转换字节保存
  2. RN中布局样式的写法
  3. WCFAppFabric :异常消息: 内存入口检查失败
  4. JAVA SE学习day_12:集合的排序、队列、栈结构
  5. python教程第四版pdf下载-笨办法学python第四版
  6. Silverlight实用窍门系列:40.Silverlight中捕捉视频,截图保存到本地【附带实例源码】...
  7. 最后一周!导师推荐的转录组和可视化学习捷径
  8. Python模拟登录实战,采集整站表格数据
  9. topsis综合评价法_DRG如何评价临床医师绩效——以肿瘤科为例
  10. [HDU] 1533 Going Home
  11. android关于截屏,关于android截屏知识的学习
  12. springmvc+druid+dataSource配置的两种方式
  13. 2.原子变量 CAS算法
  14. 北航计算机本科生考研,和计算机考研的师弟师妹们分享一下经验本人本科北航...
  15. Phyton pymssql连接数据库
  16. 上海地铁三号线(轻轨明珠线)各车站换乘和时刻表
  17. vsc 代码另起一行_VSCode 快捷键大全
  18. 红日安全 ATT&CK VulnStack靶场(三)
  19. android屏幕唤醒函数,android学习笔记 按电源键屏幕唤醒和屏幕睡眠流程(从上层到kernel)...
  20. 如何应对面试官的JVM调优问题

热门文章

  1. Linux里检查的一些目录!
  2. 主成分分析(PCA):通过图像可视化深入理解
  3. 机器视觉检测中的图像预处理方法
  4. 在 Google Colab 中使用 OpenCV 进行图像处理简介
  5. 收藏 | 深度学习在计算机视觉领域的应用总结
  6. 使用Python+OpenCV+dlib为人脸生成口罩
  7. 微信公众平台开发(82) 天气预报
  8. 转:项目报告应该汇报什么内容?
  9. (转自PHPer)成长的选择
  10. php 爬虫去重,浅谈动态爬虫与去重(续)