zoukankan      html  css  js  c++  java
  • P1417 烹调方案[背包]

    题目背景

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

    解析:

    目前为止第一道当我觉得“卧槽!还有这种操作?!”的一道题目。
    upd:2019-7-8
    这道题其实可以联系到一些贪心的思想,比如P1080 【NOIP 2012】 国王游戏这题。


    乍一看,就是一个01背包。

    说实话一开始我也对这个与背包容量(也就是时间)有关的费用大小有所顾虑,我还以为就是个泛化背包,没啥别的。毫无疑问写出来交上去爆0,也是在预料之中的。如果隐隐约约感觉到当前时刻对价值的影响,那么就说明方向对了。

    实际上,我们会发现对于任意两个相邻的食材(x)(y),显然先做(x)和先做(y)是会得到不同的价值的。如果把(x)(y)先做,那(y)的价值就有损失,反之(x)的价值有损失。但是我们并不知道是把(x)放在前面最优还是把(y)放在前面最优。

    我们可以稍微比较一下:

    (x)放在前面时:(a[x]- (t+c[x])*b[x]+a[y]-(t+c[y]+c[x])*b[y])

    (y)放在前面时:(a[y]-(t+c[y] )*b[y]+a[x]-(t+c[x]+c[y])*b[x])

    如果要整体最优,那我们势必要让任何时刻有一式(>)二式。

    化简后得到(c[x]*b[y]<c[y]*b[x])

    我们只要在01背包之前对输入数据排个序就行了。

    妙哉。

    参考代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 100010
    #define MOD 2520
    #define E 1e-12
    #define ll long long
    using namespace std;
    ll dp[N];
    int t,n,b[N];
    struct rec{
    	ll a,b,c;
    }v[N];
    //a[x]-(t+c[x])*b[x]+a[y]-(t+c[y]+c[x])*b[y] 若x在前 
    //a[y]-(t+c[y])*b[y]+a[x]-(t+c[x]+c[y])*b[x] 若y在前 
    bool operator<(rec a,rec b)
    {
    	return a.c*b.b<b.c*a.b;
    }
    int main()
    {
    	scanf("%d%d",&t,&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&v[i].a);
    	for(int i=1;i<=n;i++) scanf("%lld",&v[i].b);
    	for(int i=1;i<=n;i++) scanf("%lld",&v[i].c);
    	ll ans=-INF;
    	sort(v+1,v+n+1);
    	for(int i=1;i<=n;i++)
    	 for(int j=t;j>=v[i].c;j--){
    	 	dp[j]=max(dp[j],dp[j-v[i].c]+v[i].a-j*v[i].b);
    	 	ans=max(ans,dp[j]);
    	 }
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11147917.html
Copyright © 2011-2022 走看看