背包问题:
- 知识点回顾:传送门:https://blog.youkuaiyun.com/yandaoqiusheng/article/details/84782655/
代码模板:
0 1背包问题
完全背包问题:
多重背包问题:
-
0 1 背包问题(带排序)
-
hdu 3466
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3466
题目:最近,iSea去了一个古老的国家。这么长时间以来,它是世界上最富有和最强大的王国。结果,即使这个国家不再富裕,这个国家的人民仍然感到非常自豪。
商家是最典型的商家,每个商家仅售出一件商品,价格为Pi,但如果您的钱少于Qi,他们会拒绝与您进行交易,并且iSea评估每件商品的值为Vi。
如果他有M个货币单位,那么iSea可以获得的最高价值是多少?
代码:
#include<stdio.h>
#include<memory.h>
#include<algorithm>
using namespace std;
const int maxn = 505;
const int maxm = 5005;
int p[maxn],q[maxn],v[maxn];
int dp[maxm];
int n,m;
struct node{
int p;
int q;
int v;
}a[maxn];
bool cmp1(node a,node b){
return (a.p - a.q) > (b.p - b.q);
}
void init(){
memset(dp,0,sizeof(dp));
}
int main(){
while(scanf("%d %d",&n,&m)!= EOF){
init();
for(int i = 0;i < n;i ++){
scanf("%d %d %d",&a[i].p,&a[i].q,&a[i].v);
}
sort(a, a+n, cmp1);
for(int i = 0;i < n;i ++){
for(int j = m;j >= a[i].q;j --){
dp[j] = max(dp[j],dp[j - a[i].p]+a[i].v);
}
}
printf("%d\n",dp[m]);
}
return 0;
}
- hdu 2602
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2602
#include<stdio.h>
#include<memory.h>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int t;
int n,v;//n表示骨头的数量,v表示包的体积
struct node{
int t;//表示骨骼值
int v; //表示体积
}bone[maxn];
int dp[maxn];
int main(){
scanf("%d",&t);
while(t -- ){
//读入信息
scanf("%d %d\n",&n,&v);
for(int i = 0;i < n;i ++){
scanf("%d",&bone[i].t);
}
for(int i = 0;i < n;i ++){
scanf("%d",&bone[i].v);
}
memset(dp,0,sizeof(dp));
//开始0 1背包问题
for(int i = 0;i < n;i ++){
for(int j = v;j >= bone[i].v;j --){
dp[j] = max(dp[j],dp[j - bone[i].v]+bone[i].t);
}
}
printf("%d\n",dp[v]);
}
return 0;
}
- hdu 1203
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,m;
const int maxn = 10010;
struct node{
int a;
float b;
}sch[maxn];
float dp[maxn];
void init(){
for(int i = 0;i <= n;i ++){
dp[i] = 1;
}
}
int main(){
while(scanf("%d %d",&n,&m)&&(n > 0)||(m > 0)){
for(int i = 0;i < m;i ++){
scanf("%d %f",&sch[i].a,&sch[i].b);
}
//找一个学校的offer都没有收到的最小概率。
init();
dp[0] = 1;
for(int i = 0;i < m;i ++){
for(int j = n;j >= sch[i].a;j --){
dp[j] = min(dp[j],dp[j - sch[i].a]*(1-sch[i].b));
}
}
//至少有一个学校offer的最大概率
printf("%.1f%%\n",(1-dp[n])*100);
}
return 0;
}
- hdu 2546
#include<stdio.h>
#include<algorithm>
#include<memory.h>
//可以转变为01背包问题,求最大花费,然后用总金额剪掉,即为所求。
using namespace std;
const int maxn = 1005;
int n,m;
int v[maxn];
int dp[maxn];
int main(){
while(scanf("%d",&n)&&(n > 0)){
for(int i = 0;i < n;i ++){
scanf("%d",&v[i]);
}
scanf("%d",&m);
if(m <= 4){//什么都买不了
printf("%d\n",m);
continue;
}
memset(dp,0,sizeof(dp));
m = m-5;//剩下5块钱,去买最多的菜
sort(v,v+n);
//求最大花费
for(int i = 0;i < n-1;i ++){
for(int j = m;j >= v[i];j --){
dp[j] = max(dp[j],dp[j-v[i]] + v[i]);
}
}
int ans = m+5 - (dp[m] + v[n-1]);
printf("%d\n",ans);
}
return 0;
}
完全背包问题:忘了贴代码
多重背包问题:
- hdu 1059
#include<stdio.h>
#include<memory.h>
#include<algorithm>
using namespace std;
struct node{
int num;
int v;//表示价值
}cor[6];
const int maxn = 360005;
int n[6] = {0};
int sum = 0;
int sum1 = 0;
int cnt = 0;
int dp[maxn];
int main(){
for(int i = 0;i < 6;i ++){
cor[i].v = i+1;
}
while(scanf("%d %d %d %d %d %d",&n[0],&n[1],&n[2],&n[3],&n[4],&n[5])){
if((n[0]||n[1]||n[2]||n[3]||n[4]||n[5]) == 0){
break;//全0 退出
}
cnt ++;
memset(dp,0,sizeof(dp));
sum = 0;
for(int i = 0;i < 6;i ++){
cor[i].num = n[i];
sum += n[i]*cor[i].v;//得到钻石的总价值
}
sum1 = sum/2;
if(sum1 + sum1 != sum){
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
continue;
}
for(int i = 0;i < 6;i ++){
int num = min(cor[i].num,sum1/cor[i].v);
for(int k = 1;num > 0;k <<= 1){
if(k > num) k = num;
num -= k;
for(int j = sum1;j >= k*cor[i].v;j --){
dp[j] = max(dp[j],dp[j - k*cor[i].v] +k*cor[i].v);
}
}
}
if(dp[sum1] == sum1){
printf("Collection #%d:\nCan be divided.\n\n",cnt);
}
else{
printf("Collection #%d:\nCan't be divided.\n\n",cnt);
}
}
return 0;
}
- hdu 2844
#include<stdio.h>
#include<memory.h>
#include<algorithm>
using namespace std;
int n,m;
const int maxn = 100050;
//const int maxm = 100050;
struct node{
int num;//数量
int v;//价值
}coin[maxn];
int dp[maxn];
int main(){
while(scanf("%d %d",&n,&m)){
if((n == 0)||(m == 0)){
break;//输入结束
}
for(int i = 0;i < n;i ++){
scanf("%d",&coin[i].v);
}
for(int i = 0;i < n;i ++){
scanf("%d",&coin[i].num);
}
memset(dp,0,sizeof(dp));
for(int i = 0;i < n;i ++){
int num = min(coin[i].num,m/coin[i].v);
for(int k = 1;num > 0;k <<= 1){
if(k > num) k = num;
num -= k;
for(int j = m;j >= k*coin[i].v;j --){
dp[j] = max(dp[j],dp[j - k*coin[i].v] + k*coin[i].v);
}
}
}
// for(int i = 0;i < n;i ++){
// for(int j = m;j >= 0;j --){
// for(int k = 0;k <= coin[i].num;k ++){
// if(j >= k*coin[i].v){
printf("j = %d,k = %d,i = %d\n",j,k,i);
printf("%d %d\n",dp[j],dp[j - k*coin[i].v] + k*coin[i].v);
// dp[j] = max(dp[j],dp[j - k*coin[i].v] + k*coin[i].v);
printf("%d\n",dp[j]);
//
// }
// }
// }
// }
int ans = 0;
for(int i = 1;i <= m;i ++){
if(dp[i] > 0){
ans ++;
}
}
printf("%d\n",ans);
}
return 0;
}
- hdu 2191
暴力会wa,但是二进制优化成01背包就可以跑得过,我也不懂为啥
#include<stdio.h>
#include<memory.h>
#include<algorithm>
using namespace std;
int c;
int n,m;
const int maxn = 105;
struct node{
int p;//价格
int w;//重量
int n;//袋数
}rice[maxn];
int dp[maxn];
int main(){
scanf("%d",&c);
while(c --){
scanf("%d %d",&n,&m);
for(int i = 0;i < m;i ++){
scanf("%d %d %d",&rice[i].p,&rice[i].w,&rice[i].n);
}
memset(dp,0,sizeof(dp));
// for(int i = 0;i < m;i ++){
// for(int j = n;j >= 0;j --){
// for(int k = 0;k <= rice[i].n;k ++){
// if(j - k*rice[i].p >= 0){
// dp[j] = max(dp[j],dp[i - k*rice[i].p]+ k*rice[i].w);
// }
// }
// }
// }
for(int i = 0;i < m;i ++){
int num = min(rice[i].n,n/rice[i].p);
for(int k = 1;num > 0;k <<= 1){
if(k > num) k = num;
num -= k;
for(int j = n;j >= k*rice[i].p;j --){
dp[j] = max(dp[j],dp[j - k*rice[i].p] + k*rice[i].w);
}
}
}
printf("%d\n",dp[n]);
}
return 0;
}
- hdu 3535
wa代码,猪脑想不通啊想不通
#include<stdio.h>
#include<algorithm>
#define INF 1e9
using namespace std;
const int maxn = 10005;
const int maxm = 105;
int n,t;//n组作业,t分钟供他完成
int cnt = 0;
struct node{
int time;//表示完成这项工作所需要的时间
int h;//表示这个工作能带来的开心值
int num;//表示这个工作的类型
}job[maxn];
int dp[maxm];
bool cmp1(node a,node b){
return a.num < b.num;
}
int main(){
while(scanf("%d %d",&n,&t) != EOF){
cnt = 0;
for(int i= 0;i < n;i ++){
int m,s;
scanf("%d %d",&m,&s);
for(int j = 0;j < m;j ++){
job[cnt].num = s;
scanf("%d %d",&job[cnt].time,&job[cnt].h);
cnt ++;
}
}
sort(job,job+cnt,cmp1);
printf("---------------\n");
for(int i = 0;i < cnt;i ++){
printf("%d %d %d\n",job[i].time,job[i].h,job[i].num);
}
printf("\n--------------\n");
for(int i = 0;i <= t;i ++)
dp[i] = -INF;
dp[0] = 0;
//读入输入结束。
for(int i = 0;i <cnt ;i ++){
if(job[i].num == 0){
for(int j = job[i].time;j <= t;j ++){
dp[j] = max(dp[j],dp[j - job[i].time] + job[i].h);
printf("0:dp[%d] = %d\n",j,dp[j]);
}
}
else if(job[i].num == 1){
for(int j = t;j >= job[i].time;j --){
dp[j] = max(dp[j],dp[j - job[i].time] + job[i].h);
printf("1:dp[%d] = %d\n",j,dp[j]);
}
}
else if(job[i].num == 2){
for(int j = job[i].time;j <= t;j ++){
dp[j] = max(dp[j],dp[j - job[i].time] + job[i].h);
printf("2:dp[%d] = %d\n",j,dp[j]);
}
}
}
printf("%d\n",dp[t]);
}
return 0;
}