NYOJ747 - 蚂蚁的难题(三)(贪心+DP)

2 篇文章 0 订阅

题目链接 NYOJ747

【题意】

蚂蚁的难题(三)

时间限制: 2000 ms  |            内存限制: 65535 KB
难度: 4
描述

蚂蚁终于把尽可能多的食材都搬回家了,现在开始了大厨计划。

已知一共有 件食材,每件食材有一个美味度 Ai 和新鲜度 Bi , 如果蚂蚁在第t时刻将第i样食材烹饪成功,则得到Ai-t*Bi 的美味指数,当然,用第i件食材做饭要花去 Ci 的时间。

众所周知,蚂蚁的厨艺不怎么样,所以他需要你设计做饭方案使得在时间  内完成的美味指数最大。
输入
有多组测试数据。
第一行是两个正整数,表示蚂蚁的做饭时间T和食材个数n。(n<=50, 1<=T<=100000)。
接下来n行,每行有三个数,Ai,Bi,Ci。分别代表美味度、新鲜度和用该食材做饭花费的时间。(0<Ai,Bi,Ci<=100000).
输出
输出一个数字,表示最大美味指数
样例输入
6 1
200 5 1
样例输出
195

 

【分析】

很像01背包,一开始知道需要先贪心排序,但是怎么也找不到如果排序,贪心还是太弱,后来看了出题人的博客才知道;需要用相邻的两个物品1和2;

然后分别写出1先做和2先做可以得到的最大价值,并且假设现在已经是T时刻:

如果1物品先做:A[1]-(P+C[1])*B[1]+A[2]-(P+C[1]+C[2])*B2;(1)

如果2物品先做:A[2]-(P+C[2])*B[2]+A[1]-(P+C[1]+C[2])*B1;(2)

则可以按照(1)>(2)来排序,化简(1)>(2)为C[2]*B[1]>C[1]*B[2];

接下来直接01背包就可以了

【AC代码】32ms

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 100001
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
struct NODE{
	int a, b, c;
}p[51];
int ans, ch, dp[MAXN];

int in()
{
	while((ch = getchar()) < '0' || '9' < ch);
	ans = ch-'0';
	while((ch = getchar()) >= '0' && '9' >= ch) ans = ans*10+ch-'0';
	return ans;
}
inline bool cmp(const NODE& a, const NODE& b){return b.c*a.b>a.c*b.b;}
int main()
{
#ifdef SHY
	freopen("e:\\1.txt","r",stdin);
#endif
	int m, n;
	while(~scanf("%d %d%*c", &m, &n))
	{
		int ans = 0;
		for (int i = 0; i < n; i++)
		{
			p[i].a = in();
			p[i].b = in();
			p[i].c = in();
		}
		sort(p,p+n,cmp);
		memset(dp,0,sizeof(dp));
		for (int i = 0; i < n; i++)
		{
			for (int j = MIN(m,p[i].a/p[i].b); j >= p[i].c; j--)//剪枝,T<=A/B && T <= M
				dp[j] = MAX(dp[j], dp[j-p[i].c]+p[i].a-j*p[i].b);
		}
		for (int i = 0; i <= m; i++)
			ans = max(ans,dp[i]);
		printf("%d\n", ans);
	}
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值