JZOJ 4693 疯狂的火神【NOIP2016提高A组模拟8.14】

来源:互联网 发布:idc数据引用授权书 编辑:程序博客网 时间:2024/04/30 19:52

疯狂的火神

题目描述

火神要挑战n个人。
t分钟的时间。
每个人的价值由一个三元组(a,b,c)组成,表示如果火神在第x分钟单挑完这个人,他就会得到a-b*x的经验值,并且他需要c分钟来打倒这个人。
问最多能获得多少经验值?

数据范围

对于100%的数据1≤n≤1000,1≤t≤3000,1≤Ci≤t,Ai≤10^6
保证每个人贡献的经验值到训练结束都不会变成负数

题解

假设先打第i个人比先打第j个人更优,设当前的时刻为K,则满足

AiBi(K+Ci)+AjBj(K+Ci+Cj)>AjBj(K+Cj)+AiBi(K+Cj+Ci)

i,j为连续两个人)
化简,得

BiCi>BjCj

我们就按照BiCi从大到小排序确定优先选择顺序。

剩下的,只需按照优先顺序选择某些人来单挑就可以了。这相当于一个背包问题,使用动态规划来解决。Fi表示恰好用了 i 分钟的最高经验值。
状态转移方程为Fi=max(FiFiCj+Aj-Bji)。
答案为Max1<=i<=tFi

Code(Pascal)

var    sh:array[0..2000] of extended;    jy:array[0..2000,1..3] of longint;    f:array[-5000..5000]of int64;    t,n,y,i,o,l,time:longint;    ans:int64;procedure qsort(l,r:longint);    var        i,j:longint;        m:extended;    begin        i:=l;        j:=r;        m:=sh[(l+r) div 2];        repeat            while sh[i]>m do inc(i);            while sh[j]<m do dec(j);            if i<=j then            begin                sh[0]:=sh[i];                sh[i]:=sh[j];                sh[j]:=sh[0];                jy[0]:=jy[i];                jy[i]:=jy[j];                jy[j]:=jy[0];                inc(i);                dec(j);            end;        until i>j;        if l<j then qsort(l,j);        if i<r then qsort(i,r);    end;function max(a,b:int64):int64;    begin        if a>b then exit(a)        else exit(b);    end;begin    readln(t);    for y:=1 to t do    begin        readln(n,time);        for i:=1 to n do        begin            readln(jy[i,1],jy[i,2],jy[i,3]);            sh[i]:=jy[i,2]/jy[i,3];        end;        qsort(1,n);        for l:=-time to time do        f[l]:=-maxlongint;        f[0]:=0;        for i:=1 to n do        for l:=time downto 1 do        f[l]:=max(f[l],f[l-jy[i,3]]+jy[i,1]-jy[i,2]*l);        ans:=0;        for i:=1 to time do        ans:=max(ans,f[i]);        writeln(ans);    end;end.
4 0
原创粉丝点击