解题报告 solve

3.solve(solve.pas/c/cpp)

描述

dsqwwe每个月都有m(0<=m<=1000)元的零花钱,他现在有n(n<=300)项消费计划,每个消费计划消耗2种费用,一种是要花掉当前月的零花钱,另一种是要花掉下一个月的零花钱,每个月的零花钱不能超支,若一个月的零花钱不能用完,dsqwwe会把钱花在其他地方,也就是说,每个月剩余的零花钱不会留给下一个月。问dsqwwe想要完成他所有的消费计划最少需要几个月。

计划要顺序完成。

输入(solve.in)

  第一行:m,n

  接下来的n行,每行两个整数a,b,描述一种消费计划,a代表花掉当前月的钱的数目,b代表花掉下个月的钱的数目(a,b<=m)

输出(solve.out)

  需要最少的月数

样例输入:

100 5

40 20

60 20

30 50

30 50

40 40

样例输出:

5

样例解释:

+------+-------+--------+---------+---------+--------+
|      |零花钱 |解决问题| 当前支付| 下月预支|月底结余|
|月份  |       |        |         |         |        |
+------+-------+--------+---------+---------+--------+
| 1    | 100   | 1, 2   | 40+60   | 0       | 0      |
| 2    | 100   | 3, 4   | 30+30   | 20+20   | 0      |
| 3    | 100   | -none- | 0       | 50+50   | 0      |
| 4    | 100   | 5      | 40      | 0       | 60     |
| 5    | 100   | -none- | 0       | 40      | 60     | 
+------+-------+--------+---------+---------+--------+

DP 

首先,开 f[i,j] 表示前 个月做 个任务,最后一个月所能最多剩下的钱。

然后,分析,枚举最后一个月做了最后 个任务,然后判断,也就是,这 个任务可以压缩到 个月来完成而不会预支,也就是总钱数在 以下,然后,取最大值转移。

维的 DP 

 

program liukeke;

var

  a,b:array[0..301] of longint;

  f:array[0..601,0..301] of longint;

  x1,x2,n,m,i,j,k,ans:longint;

 

function max(a,b:longint):longint;

begin

 if a>b then exit(a);

 exit(b);

end;

 

begin

  assign(input,'solve.in');reset(input);

  assign(output,'solve.out');rewrite(output);

  readln(m,n);

  for i:=1 to n do

  begin

    readln(x1,x2);

a[i]:=a[i-1]+x1;

b[i]:=b[i-1]+x2;    // a,b 为 累和。

  end;

  fillchar(f,sizeof(f),128);  

  f[0,0]:=m;

  while true do

  begin

    inc(ans);

for j:=1 to n do

  for k:=0 to j do

    if (f[ans-1,k]>=a[j]-a[k])and(m>=(b[j]-b[k])) then

begin

                 f[ans,j]:=max(f[ans,j],m-(b[j]-b[k]));

  if f[ans,j]=m then break;   //不能更大值了

end;

if f[ans,n]>=0 then break;  //做完了

  end;

  writeln(ans+1);  //最后一拨任务影响的是两个月。

  close(input);

  close(output);

end.

 

原文地址:https://www.cnblogs.com/SueMiller/p/2237119.html