题目背景
由于你的帮助,火星只遭受了最小的损失。但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
解析:
如果没有b[i]这个属性的话就是明显的01背包问题。
现在考虑相邻的两个物品,假设现在已经耗费p的时间,那么分别列出代价:
1、第一个 a1 b1 t1
2、第二个 a2 b2 t2
先做第一个物品: a1 - (p+t1)*b1 + a2 - (p+t1+t2) *b2
先做第二个物品: a2 - (p+t2)*b2 + a1 - (p+t1+t2) *b1
对这两个式子化简,得到①>②的条件是 t1 * b2 < t2 * b1
发现只要满足这个条件的物品对(x,y),x在y前的代价永远更优。
因此可以根据这个条件进行排序,之后就是简单的01背包了。
方法有两种一维和二维都可以,题目中有些必须用long long ,这点emmm...坑,详见代码。
(1)一维dp
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn=100000+10;
ll dp[maxn];
struct node
{
ll a,b,t;
}p[maxn];
bool cmp(node x, node y)
{
return x.t * y.b < y.t * x.b;
}
int main()
{
int T,n;
cin>>T>>n;
memset(p,0,sizeof(p));
memset(dp,0,sizeof(dp));
for(ll i = 0; i < n; i++) cin >> p[i].a;//看好输入数据方式,坑
for(ll i = 0; i < n; i++) cin >> p[i].b;
for(ll i = 0; i < n; i++) cin >> p[i].t;
sort(p,p+n,cmp);
ll ans=0;
for(ll i=0;i<n;i++){
for(ll j=T;j>=p[i].t;j--){
dp[j]=max(dp[j],dp[j-p[i].t]+p[i].a-j*p[i].b);
ans=max(ans,dp[j]);
}
}
cout<<ans<<endl;
return 0;
}
(2)二维dp
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn=100000+10;
ll dp[100][maxn];
struct node
{
ll a,b,t;//必须用ll
}p[100];
bool cmp(node x, node y)//一定一定要先排序
{
return x.t * y.b < y.t * x.b;
}
int main()
{
int T,n;
cin>>T>>n;
memset(p,0,sizeof(p));
memset(dp,0,sizeof(dp));
/*for(ll i=0;i<n;i++){//看好输入数据方式,坑
cin>>p[i].a>>p[i].b>>p[i].t;
}*/
for(int i = 0; i < n; i++) cin >> p[i].a;
for(int i = 0; i < n; i++) cin >> p[i].b;
for(int i = 0; i < n; i++) cin >> p[i].t;
sort(p,p+n,cmp);
ll ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<=T;j++){
if(j<p[i].t ) dp[i+1][j]=dp[i][j];
else {
ll v=p[i].a-j*p[i].b;
dp[i+1][j]=max(dp[i][j],dp[i][j-p[i].t]+v);
}
ans=max(ans,dp[i+1][j]);
}
}
cout<<ans<<endl;
return 0;
}