ZOJ-1013-Great Equipment

有n辆坦克可以承载不同重量、体积的头盔、铠甲、靴子,这三件物品分别有不同的防御值,数量不同的头盔、铠甲、靴子可以在一起形成更大防御值的组合。每辆坦克可以承载的重量、体积各不相同,最后求出最大防御值

每辆车可以对这三件物品组成有限的组合,关键是在每辆车的各种组合中各挑出一种可能最后遍历出最大的防御值。这里要解的是全局最优,局部最优的组合不一定适合全局最优。比如0<=m<=n,在前m辆车三种物品的组合形成最大的防御值,到前n辆车找到最大防御值时,这时前m辆车的三种物品的组合可能就跟单纯前m辆车对应最大防御值时的组合不一样。

每辆坦克可以承载的重量和体积是固定的,那么也就是说如果确定了一辆坦克承载的头盔和铠甲的数量,就可以求出坦克可以承载的剩余重量和体积,靴子的数量便随之确定了。求这n辆坦克组成的最大防御值,计算这个防御值,其实最后要得成的是这n辆坦克累积承载的头盔、铠甲、靴子数量。这里以x、y、z代表第n辆坦克承载的头盔、铠甲、靴子数量,dp[n-1][A][B]代表前n-1辆坦克,在头盔的累积数量为A,铠甲累积数量为B的情况下,靴子的数量,则dp[n][A+x][B+y]=max(dp[n-1][A][B]+z,dp[n][A+x][B+y])

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
 
using namespace std;
 
struct Element{
	int weight;//重量 
	int size;//体积 
	int defend;//防御值 
}elements[3];
 
struct Caravan{
	int weight;
	int size;
}caravans[100];
 
int num;//0 <= n <= 100
int helmNum,armorNum,bootNum,equipment_defend;
 
void initData(int n){
	//输入头盔、铠甲、靴子的重量、体积、防御值 
	for(int i=0;i<3;i++){
		cin>>elements[i].weight>>elements[i].size>>elements[i].defend;
	}
	cin>>helmNum>>armorNum>>bootNum>>equipment_defend;
	//输入n辆车可以承载的重量、体积 
	for(int i=0;i<n;i++){
		cin>>caravans[i].weight>>caravans[i].size;
	}
}
int func(int x){
	return x>0? x:0;
}
//计算x个头盔、y个铠甲、z个靴子的防御值 
int calculateDefend(int x,int y,int z){
	int combine_num=99999999;
	if(helmNum>0){
		combine_num=min(combine_num,x/helmNum);
	}
	if(armorNum>0){
		combine_num=min(combine_num,y/armorNum);
	}
	if(bootNum>0){
		combine_num=min(combine_num,z/bootNum);
	}
	int all_defend=combine_num*equipment_defend+func(x-helmNum*combine_num)*elements[0].defend+func(y-armorNum*combine_num)*elements[1].defend+func(z-bootNum*combine_num)*elements[2].defend;
	return all_defend;
}
 
int maxDefend(){
	int x=0;
	int y=0;
	int max_defend=0;
	int temp=0;
	int dp[2][501][501];
	int preMaxHelm=0;
	int preMaxArmor=0;
	int maxHelm=0;
	int maxArmor=0;
	int pre=0;
	int now=1;
	
	memset(dp[0],0,sizeof(dp[0]));
	
	for(int i=0;i<num;i++){
		memset(dp[now],-1,sizeof(dp[now]));
		
		maxHelm=min(caravans[i].weight/elements[0].weight,caravans[i].size/elements[0].size);//第i辆车最多可以承载的头盔数量 
		if(maxHelm>500){
			maxHelm=500;
		}
		for(int j=0;j<=maxHelm;j++){//头盔数量 
			int remainW=caravans[i].weight-j*elements[0].weight;//第i辆车载完j个头盔剩余可以承载的重量 
			int remainS=caravans[i].size-j*elements[0].size;//第i辆车载完j个头盔剩余可以承载的体积 
			
			maxArmor=min(remainW/elements[1].weight,remainS/elements[1].size);//第i辆车载完j个头盔最多可以承载的铠甲数量
			
			if(maxArmor>500){
				maxArmor=500;
			}	
			
			int maxBoot=0;
			
			for(int d=0;d<=maxArmor;d++){
				int remainWe=remainW-d*elements[1].weight;
				int remainSi=remainS-d*elements[1].size;
					
				//第i辆车载完j个头盔、d个铠甲最多可以承载的靴子数量 
				maxBoot=min(remainWe/elements[2].weight,remainSi/elements[2].size);
				if(maxBoot>500){
					maxBoot=500;
				}
//--------------------------已经确定三个值----------------------------					
				if(i==0){//第一辆车 
					dp[now][j][d]=maxBoot;
				}else{
					for(int e=0;e<=preMaxHelm;e++){
						for(int f=0;f<=preMaxArmor;f++){
							if(dp[pre][e][f]==-1){
								continue;
							}else{
								dp[now][e+j][f+d]=max(dp[pre][e][f]+maxBoot,dp[now][e+j][f+d]);	
							}
						}
					}
				}		
			}
		}
		preMaxHelm+=min(caravans[i].weight/elements[0].weight,caravans[i].size/elements[0].size);
		preMaxArmor+=min(caravans[i].weight/elements[1].weight,caravans[i].size/elements[1].size);
		swap(pre,now);
	}
 
	temp=0;
	max_defend=0;
	
	for(int i=0;i<=preMaxHelm;i++){
		for(int j=0;j<=preMaxArmor;j++){
			if(dp[pre][i][j]!=-1){
				temp=calculateDefend(i,j,dp[pre][i][j]);
				if(temp>max_defend){
					max_defend=temp;
				}
			}
		}
	}
	return max_defend;
}
 
int main(){
	int index=1;
	cin>>num;
	while(num!=0){
		initData(num);
		if(index>1){
			cout<<endl<<endl;
		}
		cout<<"Case "<<index<<": "<<maxDefend();
		index++;
		cin>>num;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值