日常做人系列之普及村——动态规划

 

1. P1064 金明的预算方案(0-1背包变式)

https://www.luogu.org/problemnew/show/P1064

/*思想: 枚举主件 每次枚举出现四种情况

  1. 什么都不买
  2. 只买主件
  3. 买主件和第一个附件
  4. 买主件和第二个附件
  5. 买主件和两个附件
    将全部情况考虑一下,比较一下
    注: 像这种情况很多,然后状态转移方程中数组下标很多时
    可以用函数来表示下标,防止写错,以后修复代码也方便
    */

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

int r[63][3],p[63][3];//[][..]第二个表示主副件,0 (主件),1(第一个附件),2(第二个附件) 
//r[i][j] 表示价格 ,p[i][j] 表示重要度 
int V,n;
int zhufu[63];//主副件从属: zhufu[i] 表示 主件i 的第几个附件 
int f[32000 + 5];//动态规划:f[j] 表示花钱为 j 时的价格与重要度乘积最大值 

int imp(int x, int y) {
	return x * y;
}

int cost2(int cnt, int fujian)//cnt 为主件编号,这个是算情况 3 & 4的 
{
	return imp(r[cnt][fujian],p[cnt][fujian]) + imp(r[cnt][0],p[cnt][0]);
} 

int cost3(int cnt) {
	return imp(r[cnt][1],p[cnt][1]) + imp(r[cnt][0],p[cnt][0]) + imp(r[cnt][2],p[cnt][2]);
}
 
 
int main() {
	scanf("%d%d",&V,&n);
	int a,b,c;
	for(int i = 1; i <= n; i++) {
		scanf("%d%d%d",&a,&b,&c);
		if(c == 0) {
			r[i][0] = a;
			p[i][0] = b;
		}
		else {
			r[c][++zhufu[c]] = a;
			p[c][zhufu[c]] = b;
		}
	}
	for(int i = 1; i <= n; ++i) {
		for(int j = V; j >= 0; j--) {
			if(j >= r[i][0]) {//够买主件 
				f[j] = max(f[j], f[j-r[i][0]] + imp(r[i][0],p[i][0]));
			}
			if(j >= r[i][0]+r[i][1]) {//够买第一个附件和主件 
				f[j] = max(f[j], f[j-r[i][0]-r[i][1]] + cost2(i,1));
			}
			if(j >= r[i][0]+r[i][2]) {//够买第2个附件和主件 
				f[j] = max(f[j], f[j-r[i][0]-r[i][2]] + cost2(i,2));
			}
			if(j >= r[i][0]+r[i][1]+r[i][2]) {//够都买 
				f[j] = max(f[j], f[j-r[i][0]-r[i][1]-r[i][2]] + cost3(i));
			}
		}
	}
	printf("%d",f[V]);
	return 0;
}

转载于:https://www.cnblogs.com/tyner/p/10701711.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值