题目描述
一共有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
思路:
一开始没想明白,看了 tinylic 大佬的解释后才明白的
如果没有 b 属性的话,那么是一个标准的 01 背包题
根据题意,假设现在已经耗费了 t 时间,那么有:
a[x]-(t+c[x])*b[x]+a[y]-(t+c[x]+c[y])*b[y]
a[y]-(t+c[y])*b[y]+a[x]-(t+c[y]+c[x])*b[x]
化简后,得到式1>式2的条件是 c[x]*b[y]<c[y]*b[x],因此只要满足这个条件的物品对(x,y),x在y前的代价永远最优,根据这个条件排序后,就是简单的01背包
源代码
#include<iostream>
#include<algorithm>
using namespace std;
int max(int x,int y)
{
if(x>y) return x;
else return y;
}
struct food{//结构体
long long ai;
long long bi;
long long ci;
}arr[10000000];
bool cmp(food x,food y)
{
return x.ci*y.bi<y.ci*x.bi;//比较美味度
}
long long dp[10000000]={0};
int main()
{
long long t,n;
long long i,j;
long long result=0;
cin>>t>>n; //到达地球时间与食物个数
for(i=1;i<=n;i++) cin>>arr[i].ai;//属性a
for(i=1;i<=n;i++) cin>>arr[i].bi;//属性b
for(i=1;i<=n;i++) cin>>arr[i].ci;//属性c
sort(arr+1,arr+1+n,cmp);//对各种食材的美味度进行比较
for(i=1;i<=n;i++)//遍历每种食材
for(j=t;j-arr[i].ci>=0;j--)//至各食材制作时间等于总时间为止
dp[j]=max(dp[j],dp[j-arr[i].ci]+arr[i].ai-j*arr[i].bi);//arr[i].ai-j*arr[i].bi即美味指数
for(i=1;i<=t;i++) result=max(result,dp[i]);//寻找最大值
cout<<result<<endl;
return 0;
}