背包问题小结基础DP

DP问题就是递归的一种,递归对于本人很不好理解 。

1.最少硬币问题

5种面值1,5,10,25,50.给出需要的金额总值,算最少硬币数达到该金额。

书上的解释比较好理解

#include<bits/stdc++.h>
using namespace std;
const int money = 251;
const int value = 5;
int type[value]={1,5,10,25,50};
int min1[money];	//每个金额对应在最少在硬币数量 
void solve(){
	for(int i=0;i<money;i++)
		min1[i]=INT_MAX;//int范围在最大值
	min1[0]=0; //0元0个硬币  递归出口 
	for(int i=0;i<value;i++){
		for(int j=type[i];j<money;j++){
			min1[i] = min(min1[j] , min1[ j - type[i] ] + 1);// +1 放入硬币在个数为1 
		}
	} 
}
int main(){
	int s;
	solve();
	while(cin >>s){
		cout<<min1[s]<<endl;
	}
	return 0;
}

2.Coin Change hud 2069

题目描述:

有5中面值硬币1,5,10,25,50;输入金钱s,输出组合方案的数量,s<=250,数量<=100。

#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int coin = 101;  //要求不能超过100 
const int mo = 251;		//金额不能超过250 
int dp[mo][coin] = {0};
int type[5] = {1,5,10,25,50};//5种面值 
void solve(){
	dp[0][0] = 1;
	for(int i=0;i<5;i++){ //5种面值 
		for(int j=1;j<coin;j++){ //不超过100个 
			for(int k=type[i];k<mo;k++){
				dp[k][j]+=dp[k-type[i]][j-1];
			}
		}
	}
}
int main(){
	int s;
	int ans[mo] = {0};
	solve();
	for(int i=0;i<mo;i++){		//对每个金额计算有多少种组合方案,打表 
		for(int j=0;j<coin;j++){ //从0开始注意dp[0][0]=1
			ans[i]+=dp[i][j];
		}
	}
	while(cin>>s)
		cout<<ans[s]<<endl;
	return 0;
}

3.0/1背包问题

题目描述:

有多个物品,重量不同,价值不同,以及一个容量有限的背包,一样物品要么选,要么不选,使背包的容量达最大值。

/*********
3 10
5 6
2 3
2 2
11
*********/
#include<bits/stdc++.h>
using namespace std;
const int N=1000+5;
int w[N],v[N]; 	//数组w[i]指第i件物品的重量,v[i]价值 
int dp[N][N];	//动态记录价值 
int dp1[N]; 
int n,c;		//n指有n件物品,c指背包最大承重 
int main(){
	//用dp方程建表,行表示物品[1,n],列表示背包容量[1,c] 
	//dp[i][j]表示容量为j的背包选择前i件物品的最大价值和
	memset(dp,0,sizeof(dp));//dp初始化为0 
	memset(dp1,0,sizeof(dp1));

	cin >> n >> c;
	for(int i = 1;i <= n;i++)
		cin >>w[i] >> v[i];//输入物品重量和质量 

	for(int i = 1;i <= n;i++){
		//一.j结束于w[i],不用判断 j-w[i]的正负情况 
//		for(int j = w[i];j <=c;j++){ 
//			dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]] + v[i]);
//		} 

		//二.比较容易理解
//		for(int j = 1;j<=c;j++){
//			if(j < w[i]) //第i件太重,装不下 
//				dp[i][j] = dp[i-1][j];
//			else //不选当前物品和选当前物品(背包容量变为j-w[i])两种方案求最大值
//				dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]] + v[i]); 
//		} 

		//三. 用一维数组实现
		for(int j = c;j >= w[i];j--){//从右往左,每次用到的是上一轮数据的左边,不会被覆盖
			dp1[j] = max(dp1[j],dp1[j-w[i]]+v[i]);
		}
	} 

	//printf("%d\n",dp[n][c]);
	printf("%d\n",dp1[c]);

	return 0;
}

4.完全背包问题

题目描述

设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。

输入

第一行:两个整数,M(背包容量,M<=200)和N(物品数量,N<=30);

第2..N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

输出

仅一行,一个数,表示最大总价值。

样例输入

10  4
2  1
3  3
4  5
7  9

样例输出 

 

max=12

#include<bits/stdc++.h>
using namespace std;
const int N=1000+5;
int w[35],v[35]; 	//数组w[i]指第i件物品的重量,v[i]价值 
int dp[N][N];	//动态记录价值 
int n,c;		//n指有n件物品,c指背包最大承重 
int main(){
	memset(dp,0,sizeof(dp));
	cin >> c >>n;
	
	for(int i=1;i<=n;i++)
		cin >> w[i] >> v[i];
		
	for(int i=1;i<=n;i++){
		for(int j=1;j<=c;j++){
			if(j<w[i])
				dp[i][j] = dp[i-1][j];
			else 
				//这里是重点dp[i][j-w[i]]+v[i] 
		}
	}
	
	printf("max=%d\n",dp[n][c]);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值