背包问题

  • 1. 01背包
    • [HDOJ 2955.Robberies]
    • [HDOJ 1203.I NEED A OFFER!]
    • [HDOJ 1864.最大报销额]
  • 2. 完全背包
    • [HDOJ 2159.FATE]
  • 3. 多重背包
    • [HDOJ 1171.Big Event in HDU]
  • 4.二进制优化
    • [HDOJ 2844.Coins]

1. 01背包

[HDOJ 2955.Robberies]

HDOJ 2955.Robberies

题目大意:有一个名叫Roy窃贼去抢银行,他想抢到更多的钱并且不被逮捕。

输入:
共T组数据数据。
每组数据第一行有两个数P和N,代表Roy被捕的总概率和银行的个数。
接下来N行每行两个数Pj和Mj代表被捕的概率和银行所存的钱数。
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0

输出:
能获得钱数的最大值。

分析:很明显的一个01背包问题,我们将P=1-P(不被捕的概率),p[i]=1-p[i](同理),dp[i]代表获得i价值时不被被逮捕的概率,那么就很容易得到状态转移方程为dp[i] = max ( dp[i] ,dp[i-m[i]]*p[i] ),且初始状态dp[0]=1(不偷就不会被捕)。
注意概率是相乘而不是相加

#include <iostream>
#include <cstring>
using namespace std;const int maxn=1e6+10;int t;
double p[maxn],dp[maxn];
int sum,v[maxn];int main()
{double P;int n;cin >> t;while(t--){cin >> P >> n;P=1-P;sum=0;for(int i=1;i<=n;i++) {cin >> v[i] >> p[i];p[i]=1-p[i];sum+=v[i];}memset(dp,0.0,sizeof(dp));dp[0]=1;for(int i=1;i<=n;i++){for(int j=sum;j>=v[i];j--){dp[j]=max(dp[j],dp[j-v[i]]*p[i]);}}for(int i=sum;i>=0;i--){if(dp[i]>=P){cout << i << endl;break;}}}return 0;
}

[HDOJ 1203.I NEED A OFFER!]

HDOJ 1203.I NEED A OFFER!

Problem Description
Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了。要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的。Speakless没有多少钱,总共只攒了n万美元。他将在m个学校中选择若干的(当然要在他的经济承受范围内)。每个学校都有不同的申请费用a(万美元),并且Speakless估计了他得到这个学校offer的可能性b。不同学校之间是否得到offer不会互相影响。“I NEED A OFFER”,他大叫一声。帮帮这个可怜的人吧,帮助他计算一下,他可以收到至少一份offer的最大概率。(如果Speakless选择了多个学校,得到任意一个学校的offer都可以)。

Input
输入有若干组数据,每组数据的第一行有两个正整数n,m(0<=n<=10000,0<=m<=10000)
后面的m行,每行都有两个数据ai(整型),bi(实型)分别表示第i个学校的申请费用和可能拿到offer的概率。
输入的最后有两个0。

Output
每组数据都对应一个输出,表示Speakless可能得到至少一份offer的最大概率。用百分数表示,精确到小数点后一位。

分析:同上,将概率转换求最小出不去的概率

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <bitset>
#include <map>
#include <utility>
using namespace std;const int maxn=1e6+10;double p[maxn],dp[maxn];
int v[maxn];int main()
{int n,k;while(scanf("%d%d",&n,&k)==2){if(n==0 && k==0) break;for(int i=1;i<=k;i++) {scanf("%d%lf",&v[i],&p[i]);p[i]=1-p[i];}for(int i=0;i<=n;i++) dp[i]=1;for(int i=1;i<=k;i++){for(int j=n;j>=v[i];j--){dp[j]=min(dp[j],dp[j-v[i]]*p[i]);}}printf("%.1lf%%\n",(1.0-dp[n])*100.0);}return 0;
}

[HDOJ 1864.最大报销额]

HDOJ 1864.最大报销额

现有一笔经费可以报销一定额度的发票。允许报销的发票类型包括买图书(A类)、文具(B类)、差旅(C类),要求每张发票的总额不得超过1000元,每张发票上,单项物品的价值不得超过600元。现请你编写程序,在给出的一堆发票中找出可以报销的、不超过给定额度的最大报销额。

Input
测试输入包含若干测试用例。每个测试用例的第1行包含两个正数 Q 和 N,其中 Q 是给定的报销额度,N(<=30)是发票张数。随后是 N 行输入,每行的格式为:m Type_1:price_1 Type_2:price_2 … Type_m:price_m
其中正整数 m 是这张发票上所开物品的件数,Type_i 和 price_i 是第 i 项物品的种类和价值。物品种类用一个大写英文字母表示。当N为0时,全部输入结束,相应的结果不要输出。

Output
对每个测试用例输出1行,即可以报销的最大数额,精确到小数点后2位。

分析:01背包板子,注意数据处理
单项物品是指每张发票A(或B或C)类物品之和,不是其中一项A的价值。

#include <iostream>
#include <cstring>
using namespace std;const int maxn=2e6+10;string s;
int dp[maxn],sum[maxn];int main()
{double d_Q;int n;while((cin >> d_Q >> n) && n){memset(sum,0,sizeof(sum));memset(dp,0,sizeof(dp));int tot=0;int Q=(int)(d_Q*100);int flag=1;for(int i=1;i<=n;i++){int k;double pa=0,pb=0,pc=0;cin >> k;for(int j=1;j<=k;j++){char type;double price;scanf(" %c:%lf",&type,&price);if(type=='A') pa+=price;else if(type=='B') pb+=price;else if(type=='C') pc+=price;else flag=0;}if(pa+pb+pc<=1000 && pa<=600 && pb<=600 && pc<=600 && flag) sum[++tot]=(int)((pa+pb+pc)*100);}for(int i=1;i<=tot;i++){for(int j=Q;j>=sum[i];j--){dp[j]=max(dp[j],dp[j-sum[i]]+sum[i]);}}printf("%.2lf\n",dp[Q]/100.0);}
}

2. 完全背包

[HDOJ 2159.FATE]

HDOJ 2159.FATE

Problem Description
最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能升掉这最后一级吗?

Input
输入数据有多组,对于每组数据第一行输入n,m,k,s(0 < n,m,k,s < 100)四个正整数。分别表示还需的经验值,保留的忍耐度,怪的种数和最多的杀怪数。接下来输入k行数据。每行数据输入两个正整数a,b(0 < a,b < 20);分别表示杀掉一只这种怪xhd会得到的经验值和会减掉的忍耐度。(每种怪都有无数个)

Output
输出升完这级还能保留的最大忍耐度,如果无法升完这级输出-1。

分析:先将每一类怪物S进行拆分成二进制数储存,保证能组成S以内的任何怪物数。之后做一个01背包并多一维记录杀掉的怪物个数dp[ j ][ k ] = max ( dp[ j ][ k ] , dp[ j - 1 ][ k - M[ i ]. patient ] + M[ i ]. experience )。如果说dp[ S ][ P ] < 0,说明杀够S个怪物也不能升级;如果能升级,再把dp数组扫一遍找出能够升级经验中耐心消耗的最小值。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;const int maxn=1e6+10;struct monster
{int experience;int patient;int k;
}M[maxn];int dp[110][110];
int tot=0;int main()
{int E,P,n,S;while(cin >> E >> P >> n >> S){tot=0;memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){int e,p;cin >> e >> p;int tmp=1;++tot;M[tot].experience=e;M[tot].patient=p;M[tot].k=tmp;while(tmp<=S){tmp*=2;++tot;M[tot].experience=e;M[tot].patient=p;M[tot].k=tmp;}}for(int i=1;i<=tot;i++){for(int j=1;j<=S;j++){for(int k=M[i].patient;k<=P;k++){dp[j][k]=max(dp[j][k],dp[j-1][k-M[i].patient]+M[i].experience);}}}if(dp[S][P]<E) cout << -1 << endl;else{int MIN=P;for(int i=1;i<=S;i++){for(int j=P;j>=0;j--){if(dp[i][j]>=E && MIN>j){MIN=j;}}}cout << P-MIN << endl;}}
}

3. 多重背包

[HDOJ 1171.Big Event in HDU]

HDOJ 1171.Big Event in HDU

有 n 类物品,每类物品有 m 个,价值为 V ,将它们分为价值相近的A,B两堆并输出,要保证A>=B。

分析:因为数据范围较小可以将 m 个物品拆成单独的,之后进行一个总价值为V/2的01背包就行了。

#include <iostream>
#include <algorithm>
using namespace std;const int maxn=1e6+10;
const int INF=0x3f3f3f3f;int main()
{int n;while(cin >> n){if(n<0) break;int *w = new int[maxn];int sum=0;int tot=0;int val,k;for(int i=1;i<=n;i++){cin >> val >> k;sum+=k*val;while(k--) w[++tot]=val;}int V=sum/2;int *dp = new int[maxn];for(int i=1;i<=tot;i++){for(int j=V;j>=w[i];j--){dp[j]=max(dp[j],dp[j-w[i]]+w[i]);}}cout << sum-dp[V] << " " << dp[V] << endl;delete w;delete dp;}
}

4.二进制优化

[HDOJ 2844.Coins]

HDOJ 2844.Coins

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;const int maxn=1e6+10;int a[105],A[maxn];
int c[105],C[maxn];
int dp[maxn];int main()
{int n,m;while(scanf("%d%d",&n,&m) && n && m){memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) scanf("%d",&c[i]);int tot = 0;for(int i=1;i<=n;i++){int tmp=1;while(c[i]>=tmp){tot++;A[tot]=a[i]*tmp;C[tot]=tmp;c[i]-=tmp;tmp*=2;}if(c[i]>0){tot++;A[tot]=a[i]*c[i];C[tot]=c[i];}}dp[0]=1;for(int i=1;i<=tot;i++){for(int j=m;j>=A[i];j--){if(dp[j-A[i]]) dp[j]=1;}}int ans = 0;for(int i=1;i<=m;i++){if(dp[i]) ans++;}printf("%d\n",ans);}
}

动态规划题目——背包相关推荐

  1. 动态规划——01背包

    动态规划--01背包 1. 经典"01背包" 2. "01背包"方法归纳 3. 实战 3.1 分割等和子集 3.2 最后一块石头的重量 II 3.3 目标和 3 ...

  2. 数据结构与算法学习⑥(动态规划 题解 背包和打家劫舍问题)

    数据结构与算法学习⑥(动态规划 动态规划 1.初识动态规划 1.1.从贪心说起 1.1.1.贪心的特点 1.1.2.贪心的局限性 1.1.3.贪心失效后怎么办 1.1.4.从最优化问题到递归 1.2. ...

  3. vb treeview 展开子节点_详解最长公共子序列问题,秒杀三道动态规划题目

    学算法认准 labuladong 后台回复进群一起力扣? 读完本文,可以去力扣解决如下题目: 1143.最长公共子序列(Medium) 583. 两个字符串的删除操作(Medium) 712.两个字符 ...

  4. 动态规划题目汇总(持续更新)

    动态规划题目汇总(持续更新) 目录 动态规划题目汇总(持续更新) 1. 钢条切割 问题描述 解法 2. 矩阵链乘法 问题描述 解法 3. 最长公共子序列 问题描述 解法 4. 无重复字符的最长子串 问 ...

  5. 购物打折C语言程序设计,算法提高 促销购物(动态规划+完全背包)-----------------C语言——菜鸟级...

    问题描述 张超来到了超市购物. 每个物品都有价格,正好赶上商店推出促销方案.就是把许多东西一起买更便宜(保证优惠方案一定比原价便宜).物品要买正好的个数,而且不能为了便宜而买不需要的物品. 张超拿到了 ...

  6. 算法分析-动态规划-01背包

    在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2--Wn,与之相对应的价值为P1,P2--Pn.求出获得最大价值的方案. 注意:在本题中,所有的体积值均为整数.01的意思是,每个物 ...

  7. 转:动态规划题目分类

    https://blog.csdn.net/cc_again/article/details/25866971 一.简单基础dp 这类dp主要是一些状态比较容易表示,转移方程比较好想,问题比较基本常见 ...

  8. 十一、动态规划题目相关

    学习来源: 代码随香录:https://www.programmercarl.com/ labuladong算法:https://labuladong.github.io/algo/ 动态规划 动态规 ...

  9. 动态规划01背包算法详解

    动态规划算法核心思想: 将大的问题转化为小问题进行解决. 01背包问题: 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的重量为W1,W2至Wn,与之相对应的价值为V1V2至Vn.01背 ...

最新文章

  1. awk3.0 — awk变量
  2. 传承or创新 ?解密分布式数据库自研修炼之路
  3. ZOJ 3798--解题报告
  4. boost::filesystem::equivalent的用法测试程序
  5. canvas绘制阴影
  6. 别看360完成私有化 仍有三因素阻碍中概股回归
  7. redis中list类型详解及常用命令
  8. javascript高级编程学习笔记(二)——继承
  9. Tri_integral Summer Training 9 总结
  10. 爱心函数可视化 python
  11. LaTeX中生成标题、摘要、关键词、目录方法以及自定义所需样式
  12. 小哥哥小姐姐,来尝尝 Async 函数这块语法糖
  13. mysql查询所有图书信息_PHP+MySQL使用mysql_num_rows实现模糊查询图书信息功能
  14. Verdi基础知识整理
  15. 9、MyBatis的动态SQL
  16. android 自定义长条进度条_Android 条形进度条
  17. 2021年施工员-装饰方向-通用基础(施工员)考试资料及施工员-装饰方向-通用基础(施工员)考试试卷
  18. ubuntu20.04安装搜狗sogou输入法
  19. QGIS数据可视化学习笔记00——为什么用QGIS以及QGIS设置中文界面
  20. 网易裁员,让保安把身患绝症的员工赶出公司!前网易员工亲述经历的噩梦!...

热门文章

  1. 21世纪十大热门编程语言大集合,看你适合哪一种?
  2. Cisco ❀ ICMP-互联网控制报文协议
  3. 在家里如何赚钱?5个在家赚钱的方法,让你日进斗金!
  4. DPU网络开发SDK—DPDK(六)
  5. [Unity基础]GL图像库
  6. Spire.Doc在Word中插入图片时,自适应宽度设置
  7. 淘宝补单可以补金币数据吗?大神导航,一个神奇的网站,从此开启大神之路!
  8. 从0开始入门学习Swift 01
  9. FPGA_Verilog学习之旅(3)---VGA贪吃蛇游戏
  10. DHT11温湿度传感器(基于树莓派)