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[k,p]=0,f 数组初始为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.