5-1 0-1背包 (50分)

给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。

输入格式:
共有n+1行输入: 第一行为n值和c值,表示n件物品和背包容量c; 接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。

输出格式:
输出装入背包中物品的最大总价值。

输入样例:
在这里给出一组输入。例如:

5 10
2 6
2 3
6 5
5 4
4 6
输出样例:
在这里给出相应的输出。例如:

15

回溯

#include<iostream>
#include<algorithm>
using namespace std;
int n;//物品种类
	int c;//背包容量
	double w[101];//物品重量
	double v[101];//物品价值
	double a[101];//单位 
	float cp=0.0;//当前价值
	float cw=0.0;//当前重量
	float bestp=0;//当前最优价值
	int i,j;
	
int bound(int t){
	int q=c-cw;//当前剩余重量
	int b=cp;//当前价值
	while(t<=n&&w[t]<=q){
		q=q-w[t];
		b=b+v[t];
		t++;
	} 
	if(t<=n){
		b=b+q*a[t];
	}
	return b;
}
void Knapsack(){
	for(i=0;i<n;i++){
		for(j=0;j<n-i-1;j++){
			if(a[j]<a[j+1]){
			swap(a[j],a[j+1]);
			swap(w[j],w[j+1]);
			swap(v[j],v[j+1]);
			} 
		
		}
	}
//for(i=0;i<n;i++){
//	cout<<a[i]<<" "<<w[i]<<" "<<v[i]<<endl;
//}
}

void Backtrack(int t){
	if(t>n){
		bestp=cp;
//		cout<<"bestp="<<bestp<<endl;
		return;
		
	}
	if(w[t]+cw<=c){
		cw=cw+w[t];
		cp=cp+v[t];
//		cout<<cp<<endl;
		Backtrack(t+1);
		cw=cw-w[t];
		cp=cp-v[t];
	}
	if(bound(t+1)>bestp){
		Backtrack(t+1);
	}
	
}

int main(){
	cin>>n>>c;
	for(i=0;i<n;i++){
		cin>>w[i]>>v[i];
		a[i]=v[i]/w[i];
	} 
	Knapsack();
	Backtrack(0);
	cout<<bestp;
	
} 

动态规划算法

#include<iostream>
using namespace std;
int n;//n种物品
int w[200];//存放物品重量
int v[200];// 物品价值 
int c;//背包容量
int m[200][200]; 
int main(){
	cin>>n>>c;
	int i,j;
	for(i=0;i<n;i++){
		cin>>w[i]>>v[i];
	}
	for(i=n-1;i>=0;i--){
		for(j=0;j<=c;j++){
			if(j>=w[i]){//可以装的进去 
				m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); 
			}
			else{
				m[i][j]=m[i+1][j];
			}
		}
	}
	cout<<m[0][c];
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值