HDU 1114 1248(DP,完全背包)

本文深入解析了利用完全背包问题解决HDU1114与HDU1248两道编程题目。详细介绍了初值设定、动态规划实现及关键逻辑处理,特别对比了使用不同初值设定对代码执行的影响,并通过实例代码演示了解题过程。同时,简要概述了HDU1248的简单求解策略,提供了一种快速获取最优解的方法。

HDU 1114——Piggy-Bank

这道题是直接套用完全背包问题的一道题目。刚开始做的时候给数组dp赋初值是-1,但是这道题是一道求最小值的问题,所以初值不能赋-1。本来思路是-1作为一个标记,如果是-1就进行特殊处理,可是真正在dp中间,处理有些麻烦。所以dp的初值还是赋成最大比较方便。代码如下:

#include<iostream>
using namespace std;
const int maxn=100000000;

__int64 P[505];
int W[505];
__int64 dp[10005];

int main(){
//	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--){
		int E,F;
		cin>>E>>F;
		int n;
		cin>>n;
		for(int i=0;i<n;++i){
			cin>>P[i]>>W[i]; 
		}
		int pw=F-E;
		if(pw==0){cout<<"The minimum amount of money in the piggy-bank is "<<0<<'.'<<endl;continue;}
		for(int i=0;i<=pw;++i){
			dp[i]=maxn;
		}
		dp[W[0]]=P[0];
		for(int i=W[0]+W[0];i<=pw;){
			dp[i]=dp[i-W[0]]+P[0];
			i+=W[0];
		}
		for(int i=1;i<n;++i){
			for(int j=W[i];j<=pw;++j){
				if(j==W[i]&&dp[j]==maxn){
					dp[j]=P[i];
				}
				else if(j==W[i]){
					dp[j]=min(dp[j],P[i]);
				}
				if(dp[j-W[i]]==maxn)continue;
				dp[j]=min(dp[j],dp[j-W[i]]+P[i]);
			}
		}
		if(dp[pw]==maxn)cout<<"This is impossible."<<endl;
		else cout<<"The minimum amount of money in the piggy-bank is "<<dp[pw]<<"."<<endl;
	}
	return 0;
} 

如果把代码中所有的maxn改为-1作为标记,那么存在一个问题。

假设到达第i层的时候,该硬币重量为5,价值为10。假设dp[j-5]不是-1,但是dp[j]是-1,那么存在一个问题,在执行语句dp[j]=min(dp[j],dp[j-W[i]]+P[i]);时,dp[j]永远是-1,不可能变大。

在想明白这个问题以后,尝试讲maxn改为-1,也运行通过了,代码如下:

#include<iostream>
using namespace std;
const int maxn=-1;

__int64 P[505];
int W[505];
__int64 dp[10005];

int main(){
//	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--){
		int E,F;
		cin>>E>>F;
		int n;
		cin>>n;
		for(int i=0;i<n;++i){
			cin>>P[i]>>W[i]; 
		}
		int pw=F-E;
		if(pw==0){cout<<"The minimum amount of money in the piggy-bank is "<<0<<'.'<<endl;continue;}
		for(int i=0;i<=pw;++i){
			dp[i]=maxn;
		}
		dp[W[0]]=P[0];
		for(int i=W[0]+W[0];i<=pw;){
			dp[i]=dp[i-W[0]]+P[0];
			i+=W[0];
		}
		for(int i=1;i<n;++i){
			for(int j=W[i];j<=pw;++j){
				if(j==W[i]&&dp[j]==maxn){
					dp[j]=P[i];
				}
				else if(j==W[i]){
					dp[j]=min(dp[j],P[i]);
				}
				if(dp[j-W[i]]==maxn)continue;
				if(dp[j]!=-1)
					dp[j]=min(dp[j],dp[j-W[i]]+P[i]);
				else dp[j]=dp[j-W[i]]+P[i];
			}
		}
		if(dp[pw]==maxn)cout<<"This is impossible."<<endl;
		else cout<<"The minimum amount of money in the piggy-bank is "<<dp[pw]<<"."<<endl;
	}
	return 0;
} 

HDU 1248——寒冰王座

一道超级简单的题目,代码如下:

#include<iostream>
using namespace std;

int dp[10005];
int value[3]={150,200,350};

int main(){
//	freopen("data.txt","r",stdin);
	ios::sync_with_stdio(false);
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		for(int i=0;i<=n;++i){
			dp[i]=0;
		}
		for(int i=0;i<3;++i){
			for(int j=0;j<=n;++j){
				if(j<value[i])continue;
				dp[j]=max(dp[j],dp[j-value[i]]+value[i]);
			}
		}
		cout<<n-dp[n]<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值