hdu 背包问题

背包问题:

  • 知识点回顾:传送门:https://blog.csdn.net/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;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值