HDU 2159 DP

因为题目是中文题,那么在此就不再描述。大意是一个人需要N的经验升级,身上的初始忍耐度为M,怪有K种,其中给出杀每种怪给的经验和消耗的忍耐度,已知最多杀怪S只,文能否升级,如果能的话,最大剩余忍耐度是多少。

题目分析:我们可以把这个问题转化成一个背包问题,dp[i][j][k]表示前i个怪种,消耗的忍耐度为j,选中的怪的数量为k所获得的最大经验值。并且我们可以通过滚动数组来节省空间用dp[j][k]表示打K个怪消耗忍耐度为J获得的最大经验。

于是这个题就可以转变成我们熟悉的背包问题:

如下代码(附带注释):

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 110 
using namespace std;
int dp[N][N];//dp[j][k]表示打k个怪,消耗忍耐度为j所获得的最大经验 
int main()
{
	int n,m,K,s;
	int v[N],w[N];
	while(scanf("%d%d%d%d",&n,&m,&K,&s)!=EOF)
	{
		for(int i=1;i<=K;i++)
			scanf("%d%d",&w[i],&v[i]);
		memset(dp,0,sizeof(dp));
		int ans=-1;//初始化 
		bool flag=false;//标记 
		for(int j=1;j<=m;j++)//忍耐度 
		{
			for(int i=1;i<=K;i++)//怪物的种类 即为我们空间优化掉的i 
			{
				for(int k=1;k<=s;k++)//打得怪的数量 
				{
					for(int x=0;x<=k&&x*v[i]<=j;x++)//多重集 
					{
						dp[j][k]=max(dp[j][k],dp[j-x*v[i]][k-x]+x*w[i]);//状态转移方程 
						if(dp[j][k]>=n)
						{
							flag=true;
							ans=j;
							break;
						}	
					}
					if(flag)
						break;	
				}
				if(flag)
					break;
			}
			if(flag)
				break;	
		}
		if(flag)
		cout<<m-ans<<endl;
		else
		cout<<"-1"<<endl;
	}		
	//while(1);
	return 0; 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值