合肥工业大学 OnlineJudge——1003 B-黑石部落

B-黑石部落

Time Limit: 1000 MSMemory Limit: 65536 KB
Total Submissions: 1196Accepted: 303

Description


    20分钟后,在乌瑟尔营地附近的黑石部落内,乌瑟尔派出了谈判的骑士,但活着回来的却只有骑士的马匹。由于兽人仍不愿意投降,乌瑟尔便将指挥权交给了阿尔萨斯,希望由他来组织对黑石兽人的进攻。
    阿尔萨斯需要训练自己的部队来对抗兽人。他可以训练的部队有K(K<10)种,第i种部队的一个单位需要消耗G[i]的黄金,而这个部队的战斗力是W[i]。现在阿尔萨斯有一座储量为N(N<15000)的金矿,那么他能训练出的最大战斗力是多少呢?

Input


输入包括多组数据,每组数据的第一行是两个正整数N,K。接下来有K行,每行两个正整数,分别是G[i]与W[i]。输入以文件结尾结束。

Output


每行一个数,表示该组数据下阿尔萨斯能训练出的最大战斗力。

Sample Input


10 2
6 12
4 9

Sample Output


21

Source


Gardon & Gondar

想了想就是普通的动态规划,从假设只有1黄金开始找最优解,一开始i只允许训练一个单位的时候可以看做0战斗力+训练单位的战斗力,此时可训练单位战斗力的最大值就是最大战斗力。保证开始是最优解后,之后的问题可以拆分成已知训练此单位之前的最大战斗力,判断训练此单位后是否还是最大战斗力,直到黄金达到N为止。

2018/05/09更新:

比如你有两组部队 黄金/战斗力是 4/4 和 4/5,当i=4的时候 dp[4]初始是0,j=0的时候 对应的是4/4,然后判断dp[4](目前4黄金能训练的最大战斗力)和dp[0](已知0黄金能训练的最大战斗力)+4(这个单位的战斗力)的大小,如果这个和大于dp[4]就代表找到了新的最大战斗力,然后j=1时对应4/5。dp[8]的时候 判断的就是dp[8-4](8减这个战斗力需要的黄金数,并且8之前的都是已知的最大战斗力)+这个单位的战斗力。
如果用递归的话,计算5黄金的战斗力,可以拆成1+4或者2+3。拆成1+4的时候 4又可以拆成1+3或者2+2,这样1算了两遍 2算了两遍,再拆2+3 又不知道算了多少遍,动态规划就是倒着来 先算1 2推出来3 4 5

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;

//代表部队,g表示训练一个单位需要消耗的黄金,w表示这个单位的战斗力 
struct BD {
	int g,w;
};

//用于将军队按消耗黄金从小到大排序 
bool cmp(BD a, BD b) {
	return a.g<b.g;
}

int main(void) {
	int n,k;
	while(cin>>n>>k) {
		BD bd[10];
		for(int i=0; i<k; i++) {
			cin>>bd[i].g>>bd[i].w;
		}
		//排序 
		sort(bd,bd+k,cmp);
		//初始化为0 
		int dp[15001]= {};
		for(int i=1; i<=n; i++) {
			for(int j=0;j<k;j++){
				//如果黄金足够训练这个单位 
				if(i-bd[j].g >= 0){
					//如果将i-bd[j].g黄金训练得到的最大战斗力
					//加上训练此单位的战斗力超过了之前计算的最大战斗力
					if(dp[i] < bd[j].w+dp[i-bd[j].g]){
						dp[i] = bd[j].w+dp[i-bd[j].g];
					}
				}
			}
		} 
		sort(dp,dp+n+1);
		//输出最大值 
		cout<<dp[n]<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值