真的好久没有写题解了
上次写还是在上次呢
先赞后看好习惯!
昨天打了一月份的USACO(美国信奥赛)
给我一个感触(也算是感想吧):
我是蒟蒻
我是蒟蒻
我是蒟蒻
我是蒟蒻
水内容()
言归正传看今天这道题
题目背景
由于你的帮助,火星只遭受了最小的损失。但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星。不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~
gw还是会做饭的,于是拿出了储藏的食物准备填饱肚子。gw希望能在T时间内做出最美味的食物,但是这些食物美味程度的计算方式比较奇葩,于是绝望的gw只好求助于你了。
题目描述
一共有n件食材,每件食材有三个属性,ai,bi和ci,如果在t时刻完成第i样食材则得到ai-t*bi的美味指数,用第i件食材做饭要花去ci的时间。
众所周知,gw的厨艺不怎么样,所以他需要你设计烹调方案使得美味指数最大
输入格式
第一行是两个正整数T和n,表示到达地球所需时间和食材个数。
下面一行n个整数,ai
下面一行n个整数,bi
下面一行n个整数,ci
输出格式
输出最大美味指数
输入输出样例
输入 #1
74 1 502 2 47输出 #1
408说明/提示
【数据范围】
对于40%的数据1<=n<=10
对于100%的数据1<=n<=50
所有数字均小于100,000
【题目来源】
tinylic改编
刚看:哎哟喂这不就是个01背包模板吗 就这还提高组难度
(兴致勃勃地码字……)
诶不是
他怎么还有排序标签啊喂
诶不是为什么过不去?
不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是不是为什么
是的
本题蒟蒻认为只有排序这一个难点
主要他排序的思想实在难受
正常我们写排序就是sort,然后需要用到cmp函数了对吧
重中之重来了:cmp函数
是什么思想呢?
注意看,这题在算美味值的时候,需要用到t
但是t是随时变化的
所以就涉及到两种情况:
此时有x和y这两个美食,到底先做x还是先做y
先做x:xa-tx*xb+ya-(ty+tx)*yb
先做y:ya-ty*yb+xa-(tx+ty)*xb
看不懂对吧
逐一解释
xy不用说了,t代表对应变量所用时间
然后化简
就成了:
-y.b*x.c
-x.b*y.c
因为是最大美味值所以用max
剩下的就是01模板了
没什么可说的
上AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
# define int long long
struct node{
int a, b, c;
}nodes[100005];
int dp[100005];
int t,n,ans;
bool cmp(node a,node b){
return -b.b*a.c>-a.b*b.c;
}
signed main(){
scanf("%lld%lld",&t,&n);
for(int i=1;i<=n;i++){
scanf("%lld",&nodes[i].a);
}
for(int i=1;i<=n;i++){
scanf("%lld",&nodes[i].b);
}
for(int i=1;i<=n;i++){
scanf("%lld",&nodes[i].c);
}
sort(nodes+1,nodes+1+n,cmp);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
int a=nodes[i].a,b=nodes[i].b,c=nodes[i].c;
for(int j=t;j>=c;j--){
dp[j]=max(dp[j],dp[j-c]+a-b*j);
}
}
for(int i=0;i<=t;i++){
ans=max(ans,dp[i]);
}
printf("%lld",ans);
return 0;
}