饭票题解.....猥琐题...

饭票 (bticket.pas)

 

学校的食堂在使用饭卡之前使用饭票

 

饭票并不向饭卡一样方便。比如你有15元饭票和31元饭票,则你无法付4元的饭费。

 

某天小x去食堂吃饭,手里有n种饭票,面值分别为A1An,数量分别为C1Cn

 

请你计算小x的饭票能组成多少在[1,m]区间内的面值。

 

Input (bticket.in)

第一行2个数n m,用空格隔开。

以后n个数,分别为A1..An

以后n个数,分别为C1..Cn

 

Output (bticket.out)

一个数,即问题的答案

 

Sample

 

INPUT

OUTPUT

3 10

1 2 4 2 1 1

8

 

约定

1 ≤ n ≤ 100

1 ≤ Ai ≤ m ≤ 100000

1 ≤ Ci ≤ 1000

 

不看数据范围的话,就会认为纯属水题一道!看了范围后,便会发现还有很有做的价值。

很容易想到的是O(n*m*Cmax)的算法,但是这只有50分!

于是乎,我们必须从循环过程中着手,简化算法。

我是用  f[i+a[i]]:=f[i];(if f[i]=true)  的方法。

在使用背包的时候,很多步骤是重复的......所以很慢.....

看了一牛的题解后http://www.cppblog.com/liaorc/articles/41598.html

突然有了启发:

完全可以像最大升序数列那样做!

记录最少要用多少Ai达到f[j],然后在循环的过程中更新!

这样就可以把循环压缩到O(m*n)!

代码如下:

 

 1  var  count,g,h,t,i,j,n,m,max:longint;a,b: array [ 0 .. 101 ] of  longint;
 2      v: array [ 0 .. 110001 ] of  boolean;
 3      f: array [ 0 .. 110001 ] of  longint;
 4  begin
 5       assign(input, ' bticket.in ' );reset(input);
 6       assign(output, ' bticket.out ' );rewrite(output);
 7       readln(n,m);
 8        for  i: = 1   to  n  do
 9            begin
10                read(a[i]);
11            end ;
12        for  i: = 1   to  n  do
13            begin
14                read(b[i]);
15            end ;
16       max: = 0 ;
17       fillchar(v,sizeof(v), 0 );
18       v[ 0 ]: = true;
19        for  i: = 1   to  n  do
20            begin
21                fillchar(f,sizeof(f), 0 );
22                 for  h: = 0   to  m  do
23                     begin
24                          if  h + a[i] > then  break;
25                          if  v[h]  then
26                             begin
27                                  if  f[h] < b[i]  then
28                                     begin
29                                          if   not (v[h + a[i]])  then
30                                             begin
31                                                 v[h + a[i]]: = true;
32                                                 f[h + a[i]]: = f[h] + 1 ;
33                                             end
34                                          else
35                                              begin
36                                                   if  f[h + a[i]] > f[h] + 1   then
37                                                      begin
38                                                          f[h + a[i]]: = f[h] + 1 ;
39                                                      end ;
40                                              end ;
41        
42                                     end ;
43                             end ;
44                     end ;
45                  end ;
46       count: = 0 ;
47        for  i: = 1   to  m  do
48            begin
49                 if  v[i]  then  inc(count);
50            end ;
51       writeln(count);
52       close(input);close(output);
53  end . 

测试结果如下

<?xml version="1.0" ?>

- < cena version =" 0.6.3 ">
- < result judgetime =" 40109.7472578472 ">
- < problem title =" bticket " filename =" bticket.pas " status =" 1 " hash =" 2414061685 " detail ="">
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.01 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.01 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.01 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.03 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.03 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.07 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.14 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.17 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.07 " memory =" 1188 " score =" 10 " />
  < testcase status =" 7 " exitcode =" 0 " detail ="" time =" 0.18 " memory =" 1188 " score =" 10 " />
  </ problem >
  </ result >
  </ cena >

转载于:https://www.cnblogs.com/waterfalleagle/archive/2009/10/26/1589716.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值