【背包问题】竞赛真理

题目:竞赛真理 rqnoj160

题目描述

TENSHI在经历了无数次学科竞赛的失败以后,得到了一个真理:做一题就要对一题!但是要完全正确地做对一题是要花很多时间(包括调试时间),而竞赛的时间有限。所以开始做题之前最好先认真审题,估计一下每一题如果要完全正确地做出来所需要的时间,然后选择一些有把握的题目先做。 当然,如果做完了预先选择的题目之后还有时间,但是这些时间又不足以完全解决一道题目,应该把其他的题目用贪心之类的算法随便做做,争取“骗”一点分数。根据每一题解题时间的估计值,确定一种做题方案(即哪些题目认真做,哪些题目骗”分,哪些不做),使能在限定的时间内获得最高的得分

输入格式

第一行有两个正整数N和T,表示题目的总数以及 竞赛的时限(单位秒)。以下的N行,每行4个正整数W1i 、T1i 、W2i 、T2i ,
分别表示第i题:完全正确做出来的得分,完全正确做出来所花费的时间(单位秒),“骗”来的分数,“骗”分所花费的时间(单位秒)。其中,3 ≤N ≤30,2 ≤T ≤ 1080000,1 ≤ W1i 、W2i ≤ 30000,1 ≤ T1i 、T2i ≤ T。

输出格式

直接把所能得到的最高分值输出

样例输入

样例输出

 

类似于01背包,只是有三种状态,分别判断即可,用数组f[第几题][时间]来维护,可就地滚动成f[时间]

转移方程   f[i][j] --> 做:f[i-1][j-T1i]+W1i

                             骗:f[i-1][j-T2i]+W2i

Pascal Code

program rqnoj160;

var
  n,time:longint;
  ws,wt,ps,pt:array[0..30+10] of longint;
  f:array[0..1080000+10] of longint;

procedure init;
begin
  assign(input,'rqnoj160.in');
  assign(output,'rqnoj160.out');
  reset(input);
  rewrite(output);
end;
procedure outit;
begin
  close(input);
  close(output);
  halt;
end;

procedure readdata;
var
  i:longint;
begin
  read(n,time);
  for i:=1 to n do
    read(ws[i],wt[i],ps[i],pt[i]);
end;

procedure main;
var
  i,j:longint;
begin
  for i:=1 to n do
  begin
    for j:=time downto 0 do
    begin
      if (j>=wt[i])and(f[j]<f[j-wt[i]]+ws[i]) then f[j]:=f[j-wt[i]]+ws[i];
      if (j>=pt[i])and(f[j]<f[j-pt[i]]+ps[i]) then f[j]:=f[j-pt[i]]+ps[i];
    end;
  end;
  writeln(f[time]);
end;


begin
  init;
  readdata;
  main;
  outit;
end.

 

 

 

posted @ 2012-08-19 08:54  jiangzh  阅读(271)  评论(0)    收藏  举报