Vijos 1025 2008.9.7

Vijos 1025 2008.9.7

我终于明白背包问题是倒循环还是正循环了,此文很强!

 

描述 Description  

     经过抽签选择,小智将军第一个进入考场。

  菜虫:(身上散射出华贵(?)的光芒)欢迎你,第一位挑战者!!

  小智:……(走到菜虫身后,关灯)女王陛下,虽然我们国家现在很富裕,但也请您不要浪费电来用这么大功率的灯泡。

  菜虫(汗):啊啊~~爱卿所言甚是~~那么,你的题目是……我们的情报组织探听到敌人的重要将领——小飞侠星期天会邀他的灵儿妹妹到公园去玩。公园里有很多娱乐项目,可并不是每一项他们都喜欢,所以他们对每一项都进行了“喜欢度”的评分。因为小飞侠也是一个了不起的角色,所以他一定会选择在有限时间内的最好的方案。现在要你做的就是找出在规定时间内他们选择哪几项不同的活动可以使其“喜欢度”之和达到最大,据此我们就可以知道他会在哪些地方出现,从而在那里派人看守了。

  小智:(灯泡一亮)每个地方都派人看守不就行了?!

  “当~~~”

  菜虫:(手执八公分直径炒锅,筋)……你是白痴吗?-_-##(都派人去看守的话我们会有多少桌三缺一?!)听好了,输入格式是第一行一个正整数N(1<=N<=100)表示总共的娱乐项目数;第二行一个正整数表示规定的时间t(0<t<1000);下面有N行,其中第i+2行有两个正整数fi(0<=fi<=100)和ti(0<ti<=100),分别表示对项目i的“喜欢度”和它所耗费的时间。输出的时候在第一行输出最大的“喜欢度”之和,下面给你一个样例:

input

3

5

1 2

5 5

4 3

 

output

5


program1:
program p_1025;
const maxm=1000;maxn=100;
var a,t:array[0..maxn]of longint;
      f:array[0..maxm]of longint;
      i,j,m,n,t1:longint;
begin
  fillchar(f,sizeof(f),0);
  fillchar(a,sizeof(a),0);
  fillchar(t,sizeof(t),0);
  read(n);read(m);t1:=0;
  for i:=1 to n do
  read(a[i],t[i]);
     for j:=1 to n do
       for i:=m downto 1 do{
        begin if f[i-1]>f[i] then f[i]:=f[i-1];
                 if (i-t[j]>=0)and(f[i-t[j]]+a[j]>f[i]) then
                      f[i]:=f[i-t[j]]+a[j];
         end;
write(f[m]);
end.
program 2:
program p_1025;
const maxm=1000;maxn=100;
var a,t:array[0..maxn]of longint;
      f:array[0..maxm]of longint;
      i,j,m,n,t1:longint;
begin
  fillchar(f,sizeof(f),0);
  fillchar(a,sizeof(a),0);
  fillchar(t,sizeof(t),0);
  read(n);read(m);t1:=0;
  for i:=1 to n do
  read(a[i],t[i]);
     for j:=n downto 1 do
       for i:=0 to m-1 do
        begin if f[i+1]>f[i] then f[i]:=f[i+1];
                 if (i+t[j]<=m)and(f[i+t[j]]+a[j]>f[i]) then
                      f[i]:=f[i+t[j]]+a[j];
         end;
write(f[0]);
end.

1.每个地方只能看一次,倒着推,那么,在dp时就从前面的结果中去找答案,因为,前面的结果还没有被第j个游览点影响。f[n]是结果。

若想正着推,那么,在dp时就从后面去找答案,因为后面的还没有被第j个游览点影响。f[0]是结果

2.若每个地方可以看无限次,那么,在dp时,就要从已经被第j个游览点影响的结果中去找。

3.因为是加入每个地点后,对每个时间i的影响,所以,时间i做内层循环,j做外层循环。

4.关于游览点的变量j,是正着还是倒着,都是没有关系的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值