• 动态规划-codeforces


    题目描述 

    牛牛正在打一场CF
    比赛时间为T分钟,有N道题,可以在比赛时间内的任意时间提交代码
    第i道题的分数为maxPoints[i],题目的分数随着比赛的进行,每分钟减少pointsPerMinute[i]
    这是一场比较dark的Cf,分数可能减成负数
    已知第i道题需要花费 requiredTime[i] 的时间解决
    请问最多可以得到多少分

    输入描述:

    第一行输入两个整数N,T (1 ≤ N ≤ 50, 1 ≤ T ≤ 100000)
    第二行输入n个整数maxPoints[i]
    第三行输入n个整数pointsPerMinute[i]
    第四行输入n个整数requiredTime[i]
    1 ≤ maxPoints[i],pointsPerMinute[i],requiredTime[i] ≤ 100000

    输出描述:

    输出一个整数
    示例1

    输入

    复制
    1 74
    502
    2
    47

    输出

    复制
    408
    示例2

    输入

    复制
    2 40000
    100000 100000
    1 100000
    50000 30000

    输出

    复制
    0
    示例3

    输入

    复制
    3 75
    250 500 1000
    2 4 8
    25 25 25

    输出

    复制
    1200
    示例4

    输入

    复制
    3 30
    100 100 100000
    1 1 100
    15 15 30

    输出

    复制
    97000

    思路:首先,题目有分数和完成时间,两个属性。且有时间限制。可以得出是一个01背包问题。
    但是由于题目的分数是在变化的,所以它不同于简单的背包问题。以此要算出它的性价比进行排序。先做能得分的且得分高的
    假设分数为f,每分钟减少p,花费时间是t.有两个题目i,j.假设写题时间是t1+t2;
    如果先写i题Ti=fi-pi*ti+fj-pj*(ti+tj)=fi+fj-pi*ti-pj*tj-pj*ti
    如果先写j题Tj=fj-pj*tj+fi-pi*(ti+tj)=fi+fj-pi*ti-pj*tj-pi*tj
    由Ti-Tj=pi*tj-pj*ti。所以。如果i题的性价比比j题的高,那么pi*tj>pj*ti
    所以应当将性价比高的先写。所谓是同等时间内先拿分高的。
    #include <cstdio>
    #include <cstdlib>
    #include <climits>
    #include <fstream>
    #include <algorithm>
    #include <cmath>
    #include <deque>
    #include <vector>
    #include <queue>
    #include <string>
    #include <cstring>
    #include <map>
    #include <stack>
    #include <set>
    #include <sstream>
    #include <iostream>
    using namespace std;
    
    typedef long long ll;
    const int mod = 1e9+7;
    const double PI=3.14159265358;
    const int INF=0x3f3f3f3f;
    
    struct node{
        //分数
        ll fen;
        //每分钟减少的分数
        ll minfen;
        //花费的时间
        ll time;
        //自定义排序方法
        friend bool operator <(const node a,const node b){
            return b.time*a.minfen>a.time*b.minfen;
        }
    };
    node no[52];
    //dp[i][j] i表示题数 j表示时间
    ll dp[52][100010];
    int t,n;
    
    
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
    
        cin>>n>>t;
    
        memset(dp,0,sizeof(dp));
        memset(no,0,sizeof(no));
    
        for(int i=1;i<=n;i++){
            cin>>no[i].fen;
        }
        for(int i=1;i<=n;i++){
            cin>>no[i].minfen;
        }
        for(int i=1;i<=n;i++){
            cin>>no[i].time;
        }
        //排序。将性价比高的排在前面
        sort(no+1,no+n+1);
    
        ll ans=0;
        //循环题数
        for(int i=1;i<=n;i++){
            //循环时间
            for(int j=0;j<=t;j++){
                //当前时间足够写完当前题目时
                if(j>=no[i].time){
                    //等于当前时间内完成i-1题的分数与
                    //(当前时间-这一题的时)间内完成i-1的分数加上写完这一题的分数
                    //中的最大值
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-no[i].time]+no[i].fen-no[i].minfen*j);
                }else{
                    //此时时间不够完成此题时
                    //dp等于当前时间内完成i-1题的分数
                    dp[i][j]=dp[i-1][j];
                }
                //答案等于这些方案中,分数最高的那个
                ans=max(ans,dp[i][j]);
            }
        }
        cout<<ans<<endl;
    
        return 0;
    }
  • 相关阅读:
    UVA-448
    算法提高-集合选取
    算法训练Maze
    UVA-10061
    树状数组
    前缀和
    【UVA
    统计Linux下的CPU状态信息
    Android_内部文件读取
    Android打开/data/目录以及导出文件
  • 原文地址:https://www.cnblogs.com/mzchuan/p/13591526.html
Copyright © 2020-2023  润新知