vijos-p1322 2008.11.8

vijos-p1322 2008.11.8

描述 Description  

     过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目

精确地说,他们有P (1 <= P <= 300) 道题目要做. 他们还离开了农场并且象普通人一样找到了工作. 他们的月薪是M (1 <= M <= 1000) 元.

他们的题目是一流的难题,所以他们得找帮手.帮手们不是免费的,但是他们能保证在一个月内作出任何题目.每做一道题需要两笔付款, 第一笔A_i(1<= A_i <= M)元在做题的那一个月初支付, 第二笔B_i元(1 <= B_i <= M)在做完后的下一个月初支付. 每一个月牛们用上一个月挣的钱来付款. 牛没有任何存款意识, 所以每个月的节余都回拿用去买糖吃掉了.

因为题目是相互关连的,它们必须按顺序解出. 比如,题目3必须在解题目4

之前或同一个月解出.

找出牛们做完所有题目并支付完所有款项的最短月数.

输入格式 Input Format

第一行: M 和 P;

第2...P+1行: 第i行包含A_i和B_i, 分别是做第i道题的欲先付款和完成付款.

输出格式 Output Format

   第一行: 牛们做完题目和付完帐目的最少月数.

样例输入 Sample Input

1005

4020

6020

3050

3050

4040

样例输出 Sample Output

6

分析:

 

这道题目是道DP题,由于做题是有序的,所以就有了阶段,我们用f[k,i]表示前k天完成前i道题的最小欠费,方程为f[k,i]:=min{sum_b[j+1,i]|sum_a[j+1,i]+f[k-1,j]<=m}sum_a[j,i]表示a[j]a[i]的和,sum_b亦然;结束条件是f[kp]=0f 数组初始为oo

//今天见识到了dp的循环终值是不定的题目

program p1322;
const
fin     ='psolve.in';
fou     ='psolve.out';
maxn     =300+2;
          oo                        =20000000;
var
a,b     :array[0..maxn]of longint;
sum_a,sum_b    :array[0..maxn,0..maxn]of longint;
f     :array[0..2*maxn,0..maxn]of longint;
n,p,ans     :longint;

procedure openfile;
begin
assign(input,fin);assign(output,fou);
reset(input);rewrite(output);
end;

procedure closefile;
begin
close(input);close(output);
end;

procedure init;
var
i     :longint;
begin
openfile;

readln(p,n);
for i:=1 to n do begin
    readln(a[i],b[i]);
end;
end;

procedure get_sum;
var
i,j,_sum    :longint;
begin
_sum:=0;
for i:=1 to n do begin
    _sum:=_sum+a[i];
    sum_a[1,i]:=_sum;
    for j:=2 to i do begin
     sum_a[j,i]:=sum_a[1,i]-sum_a[1,j-1];
    end;
end;

_sum:=0;
for i:=1 to n do begin
    _sum:=_sum+b[i];
    sum_b[1,i]:=_sum;
    for j:=2 to i do begin
     sum_b[j,i]:=sum_b[1,i]-sum_b[1,j-1];
    end;
end;
end;

procedure main;
var
k,i,j     :longint;
begin
get_sum;

fillchar(f,sizeof(f),0);
k:=1;f[1,0]:=0;
for i:=1 to n do f[1,i]:=oo;
repeat
    inc(k);
for i:=0 to n do
begin
f[k,i]:=oo;
     for j:=i downto 0 do begin//倒者循环更快!
      if sum_a[j+1,i]+f[k-1,j]<=p then begin//上一个月的欠费+这个月初要付的钱<=m时
       f[k,i]:=sum_b[j+1,i];//当前月的欠费就更新
       break;
      end;
     end;
    end;
until f[k,n]=0;
ans:=k;
end;

procedure print;
begin
writeln(ans);

closefile;
end;

begin
init;
main;
print;
end.


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值