切原木问题 (25分) (完全背包)

给定一根长度为N米的原木;另有一个分段价格表,给出长度L1,L2,…Li,…Lk米所对应的价格P1,P2…Pk(Li,Pi均为正整数),求切割原木分段出售所能获得的最大收益。 例如,根据下面给出的价格表,

Li 1 2 3 4 5 6 7 8 9 10
Pi 1 5 8 9 10 17 17 20 23 28
若要出售一段8米长的原木,最优解是将其切割为2米和6米的两段,这样可以获得最大收益=L2+L6=5+17=22。而若要出售一段3米长的原木,最优解是根本不要切割,直接售出。

输入格式:
首行输入N,k,紧接着第二行为k个Li(递增有序)和第三行对应的k个Pi值。 (0<N,k<1000) 。

输出格式:
对应原木的最大切割收益(题目中保证最大收益值在int范围)。

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

8 10
1 2 3 4 5  6  7  8  9  10
1 5 8 9 10 17 17 20 23 28

输出样例:
在这里给出相应的输出。例如:

22

做这个题的时候,只学过01背包,当时分析了这个题目,也想到了只是个完全背包问题,可惜之前没有遇到过这类题,还傻傻的以为完全背包就是像PTA上月饼的那道题一样,求出单价,然后按照单价从低到高的顺序排序,如果单价相同,按照代价少的排序,结果错了,之后又用递归枚举所有的情况,结果就对了一个测试点,其他测试点全部超时,唉.
完全背包代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
int dp[1005];
int cost[1005];
int value[1005];
int main() {
	int n,v;
	cin>>v>>n;
	for(int i=1; i<=n; i++) {
		cin>>cost[i];
	}
	for(int i=1; i<=n; i++) {
		cin>>value[i];
	}
	for(int i=1; i<=n; i++) {
		for(int j=cost[i]; j<=v; j++) {
			dp[j]=max(dp[j],dp[j-cost[i]]+value[i]);
		}
//		for(int i=0; i<=v; i++) {
//			cout<<dp[i]<<' ';
//			if(i==v)cout<<endl;
//		}
	}
	cout<<dp[v];
	return 0;
}

附上我写错的代码吧:
贪心算法版:
好吧,贪心版因为样例都没过所以没提交,结果现在没记录了
暴力递归版:(只过了第一个测试点)

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
using namespace std;
int a[1005];
int has[1005];
int n,k;
int max1;
void dfs(int idx,int sumid,int sumvalue){
	if(sumid==n){
		if(sumvalue>max1)max1=sumvalue;
//		cout<<sumvalue;
		return ;
	}else if(sumid>n)return;
	for(int i=idx;i<k;i++){
		dfs(i+1,sumid+has[i],sumvalue+a[has[i]]);
//		cout<<a[has[i]];
	}
}
int main(){
	cin>>n>>k;
	for(int i=0,c,d;i<k;i++){
		cin>>has[i];
	}
	for(int i=0,c,d;i<k;i++){
		cin>>a[has[i]];
	}
	dfs(0,0,0);
	cout<<max1;
}

发布了99 篇原创文章 · 获赞 13 · 访问量 2680

猜你喜欢

转载自blog.csdn.net/qq_44378358/article/details/103656215