hdu2159 FATE

27 篇文章 0 订阅
12 篇文章 0 订阅

初看是背包问题,但没有往二位费用背包上想。对于最多的杀怪数为k的条件尝试增加一维,dp[i][j]中j表示已杀的怪的数目,得到状态转移方程dp[i][j]=max(dp[i][j],dp[i-1][j-b]+a),每种怪的数目不限,对于第一维[i]是完全背包问题,采用完全背包的顺序循环方式,这样看状态转移方程第二维[j]似乎不是表示已杀的怪的数目,思路在这被卡住了。翻看了一下背包九讲找到了这个问题,以下转自背包九讲。

5 二维费用的背包问题
5.1 问题
二维费用的背包问题是指:对于每件物品,具有两种不同的费用,选择这件物品必
须同时付出这两种费用。对于每种费用都有一个可付出的最大值(背包容量)。问怎样
选择物品可以得到最大的价值。
设第i 件物品所需的两种费用分别为Ci 和Di。两种费用可付出的最大值(也即两
种背包容量)分别为V 和U。物品的价值为Wi。
5.2 算法
费用加了一维,只需状态也加一维即可。设F[i; v; u] 表示前i 件物品付出两种费用
分别为v 和u 时可获得的最大价值。状态转移方程就是:
F[i; v; u] = max{F[i - 1; v; u]; F[i - 1; v - Ci; u - Di] + Wi}
如前述优化空间复杂度的方法,可以只使用二维的数组:当每件物品只可以取一次
时变量v 和u 采用逆序的循环,当物品有如完全背包问题时采用顺序的循环,当物品
有如多重背包问题时拆分物品。
这里就不再给出伪代码了,相信有了前面的基础,读者应该能够自己实现出这个问
题的程序。
5.3 物品总个数的限制
有时,“二维费用”的条件是以这样一种隐含的方式给出的:最多只能取U 件物品。
这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为1,可以
付出的最大件数费用为U。换句话说,设F[v; u] 表示付出费用v、最多选u 件时可得
到的最大价值,则根据物品的类型(01、完全、多重)用不同的方法循环更新,最后在
f[0 : : : V; 0 : : :U] 范围内寻找答案。
5.4 二维整数域N2 上的背包问题
另一种看待二维背包问题的思路是:将它看待成N2 域上的背包问题。也就是说,
背包的容量以及每件物品的费用都是一个二维向量。而常见的一维背包问题则是自然数
域上的背包问题。所以说,一维背包的种种思想方法,往往可以应用于二位背包问题的
求解中,因为只是数域扩大了而已。
作为这种思想的练习,你可以尝试将后文中提到的“子集和问题”扩展到二维,并
试图用同样的复杂度解决。
5.5 小结
当发现由熟悉的动态规划题目变形得来的题目时,在原来的状态中加一维以满足新
的限制是一种比较通用的方法。希望你能从本讲中初步体会到这种方法。

所以,dp[i][j]中[i]应该表示忍耐度为i时,[j]应该表示最多可杀的怪为j时,这样分析的话状态转移方程才是对的。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dp[101][101];
int main(){
	int n,m,k,s;
	int a,b;
	int ii,i,j;
	while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF){
		memset(dp,0,sizeof(dp));
		for(ii=1;ii<=k;ii++){
			scanf("%d%d",&a,&b);
			for(i=1;i<=s;i++)   //i和j的循环次序是可以调换的
				for(j=b;j<=m;j++)
					dp[i][j]=max(dp[i][j],dp[i-1][j-b]+a);
		}
		if(dp[s][m]<n)
			printf("-1\n");
		else{
			int total=m;
			for(i=1;i<=s;i++)
				for(j=0;j<=m;j++)
					if(dp[i][j]>=n&&j<total)
						total=j;
			printf("%d\n",m-total);
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值