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

饭票 (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>
posted @ 2009-10-26 08:51  瀑布飞鹰  阅读(310)  评论(0编辑  收藏  举报