zoukankan      html  css  js  c++  java
  • 洛谷 OJ P1417 烹调方案 01背包

    题目背景

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

    01背包的思路,不过物品的价值会随着时间改变,因此要先排序。

    假设现在的时间是 0,有两个物品,他们的参数分别为  ai,bi,ci 和 aj,bj,cj。

    如果先放第一个物品再放第二个物品,则价值为 ai - bi*ci + aj - bj*(ci + cj)

    如果先放第二个物品再放第一个物品,则价值为 aj - bj*cj + ai - bi*(cj + ci)

    假设第一种方法要比第二种方法更优,则得到不等式 ai - bi*ci + aj - bj*(ci + cj) > aj - bj*cj + ai - bi*(cj + ci)

    将其化简后,可以得到式子  bj * ci < bi * cj

    也就是说,如果满足上面的式子,则先放第一个物品,再放第二个物品这种方法一定是最优的。

    因此将所有物品按照上面的方法进行排序后,再进行01背包,得到的结果就会使最优解。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX = 100005; 
    
    struct Node{
        long long a, b, c;
    };
    
    long long dp[MAX];
    Node node[MAX];
    int t, n;
    
    bool cmp(Node a, Node b){        
        return b.b * a.c < a.b * b.c;
    }
    
    int main(){
    //    freopen("input.txt", "r", stdin);
    //    freopen("output.txt", "w", stdout);
        
        cin >> t >> n;
        for(int i=1; i<=n; i++){
            cin >> node[i].a;
        }
        for(int i=1; i<=n; i++){
            cin >> node[i].b;
        }
        for(int i=1; i<=n; i++){
            cin >> node[i].c;
        }
        
        //按照优先级进行排序 
        sort(node+1, node+1+n, cmp);
        
        //DP  01背包 
        memset(dp, 0, sizeof(dp));
        for(long long i=1; i<=n; i++){
            long long a = node[i].a;
            long long b = node[i].b;
            long long c = node[i].c;
            for(long long j=t; j>=c; j--){
                dp[j] = max(dp[j], dp[j-c] + a - b*j);
            }
        }
        
        long long ans = 0;
        
        for(int i=0; i<=t; i++){
            ans = max(ans, dp[i]);
        }
        
        cout << ans;
        
        return 0;
    }
  • 相关阅读:
    IO复习
    递归
    转换流
    编码与解码
    打印流(printStream)
    Properties
    【转】将Visual Studio武装到底
    【转】VS2008中的自定义格式化代码
    C++开发工具的常用插件
    抽烟的注意事项
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/7382775.html
Copyright © 2011-2022 走看看