考状态的dp

我的方法可能比较奇怪

设f[i,j]表示第i个月解决j个问题可以最多解决到第几个问题

容易知道,答案(月份)不会超过2n+1;

f[i,j]=max(f[i-1,k]+j) 

复杂度为O(n^3)

代码如下

 1 var f:array[0..1000,0..500] of longint;
 2     b,a,sa,sb:array[0..500] of longint;
 3     p,y,q,i,j,k,n,m:longint;
 4 function max(a,b:longint):longint;
 5   begin
 6     if a>b then exit(a) else exit(b);
 7   end;
 8 
 9 begin
10   readln(m,n);
11   for i:=1 to n do
12   begin
13     readln(b[i],a[i]);
14     sa[i]:=sa[i-1]+a[i];
15     sb[i]:=sb[i-1]+b[i];
16   end;
17   f[1,0]:=0;
18   i:=1;
19   while i<=2*n+1 do
20   begin
21     inc(i);
22     f[i,0]:=f[i-1,0];
23     for j:=1 to n do
24     begin
25       if f[i-1,j]=0 then break;
26       f[i,0]:=max(f[i,0],f[i-1,j]);
27     end;
28     for j:=1 to n do
29     begin
30       for k:=0 to n do
31       begin
32         if (f[i-1,k]=0) and (k<>0) then break;    //后面的状态不存在,直接退
33         p:=f[i-1,k];
34         q:=f[i-1,k]+j;
35         if q>n then continue;
36         y:=f[i-1,k]-k;
37         if (sb[q]-sb[p]+sa[p]-sa[y]<=m) and (sa[q]-sa[p]<=m) then          //判断是否够这个月花的
38           f[i,j]:=max(f[i,j],f[i-1,k]+j);
39       end;
40       if f[i,j]>=n then
41       begin
42         writeln(i+1);    //注意付完款一定是下个月
43         halt;
44       end;
45       if f[i,j]=0 then break;
46     end;
47   end;
48 end.
View Code

话说代码有的地方可能写的比较冗杂……

 

posted on 2014-01-23 22:16  acphile  阅读(116)  评论(0编辑  收藏  举报