烹调方案

题目背景

由于你的帮助,火星只遭受了最小的损失。但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;
}

猜你喜欢

转载自blog.csdn.net/qq_41555192/article/details/81588955