问题8-3
对就业没有兴趣的郑来没有意识到提升实力的必要性,一直逃避解决问题。但是听了aa的培训之后,郑来有了一个梦想,就是进入aa工作!
郑来为了进入aa,需要按顺序准确地解出P(1 ≤ P ≤ 300)个问题才可以。但是由于疏于解题已经很长时间,郑来靠自己一道问题都解不出来。因此郑来请了每天都努力解题的昌洙来帮忙。之前昌洙的实力和郑来差不多,但是经过每天努力的练习,现在昌洙不论接到了怎样的问题,数量多么多的问题,都可以把接到的全部问题准确地在一个月内解出来。
努力练习的昌洙向郑来提出了需要报酬。还好,平时每个月郑来都会从父母那里得到M(1 ≤ M ≤ 1000)元的零用钱。但是不幸的是,郑来收到问题的那个月已经把零用钱都用完了。
昌洙说,各个问题的难易度都不一样,因此对第i个问题,在收到该问题那天收取A_i(1≤ A_i ≤ M)元,委托了问题的下一个月(问题解决后)收取B_i(1 ≤ B_i ≤ M)元。
另外,梦想成为时尚达人的郑来在每月末都将剩下的所有零花钱用在网上购物上。
郑来开始好奇自己收到的问题要花多长时间能解决完。请求出郑来解决所有问题所需要的最小月数。
输入
第一行输入给出空格分隔的两个自然数M,P。
从第二行开始到p+1行中输入给出两个自然数A_i和 B_i,用空格分开。
第i个问题只能在第i-1个问题解决后才能委托。
输出
输出解决郑来委托的所有问题的最小月数。
案例输入
100 5
40 20
60 20
30 50
30 50
40 40
案例输出
6
提示
+------+-------+--------+---------+---------+--------+
| | Avail |Probs | Before | After | Clothes|
|Month | Money | Solved | Payment | Payment | Money |
+------+-------+--------+---------+---------+--------+
| 1 | 0 | -none- | 0 | 0 | 0 |
| 2 | 100 | 1, 2 | 40+60 | 0 | 0 |
| 3 | 100 | 3, 4 | 30+30 | 20+20 | 0 |
| 4 | 100 | -none- | 0 | 50+50 | 0 |
| 5 | 100 | 5 | 40 | 0 | 60 |
| 6 | 100 | -none- | 0 | 40 | 60 |
+------+-------+--------+---------+---------+--------+
(100 3)(20 50)(20 40)(20 20)
+------+-------+--------+---------+---------+--------+
| | Avail |Probs | Before | After | Clothes|
|Month | Money | Solved | Payment | Payment | Money |
+------+-------+--------+---------+---------+--------+
| 1 | 0 | -none- | 0 | 0 | 0 |
| 2 | 100 | 1 | 20 | 0 | 0 |
| 3 | 100 | 2, 3 | 20+20 | 50 | 0 |
| 4 | 100 | -none- | 0 | 40+20 | 0 |
+------+-------+--------+---------+---------+--------+
#include<cstdio>
int tot_before[301], tot_after[301];
int m,p;
int d[602][301];
int main(){
scanf("%d%d", &m, &p);
tot_before[0] = 0;
tot_after[0] = 0;
int bef, aft;
for (int i = 1; i <= p; i++){
scanf("%d%d", &bef, &aft);
tot_before[i] = tot_before[i - 1] + bef;
tot_after[i] = tot_after[i - 1] + aft;
}
// first month, no problem solved,
d[0][0] = 0;
for (int i = 1; i <=p; i++) d[0][i] = -1;
int minleft = -1;
// i=every month
for (int i = 1; i <= 2 * p; i++){
// j= every problem this month
for (int j = 1; j <= p; j++){
minleft = -1;
// k=solved problem last month
for (int k = 0; k <= j; k++){
if (d[i - 1][k] != -1 // exists debt last month
&& (d[i - 1][k] + (tot_before[j] - tot_before[k])) <= m //last debt plus this month new
&& (tot_after[j] - tot_after[k]) <= m) // left to next month
{
if (minleft == -1 // debt is not initlized
|| minleft > (tot_after[j] - tot_after[k])) // debt is not minimum
minleft = tot_after[j] - tot_after[k]; // update it
}
}
// i month, solved j problem, how much debt was left to next month.
// and it is minimum..
d[i][j] = minleft;
}
}
// find which month the last problem P is solved,print it.
for (int i = 1; i <= 2 * p; i++){
if (d[i][p] != -1){
// why add 2?, first and last month are not included
printf("%d\n", i + 2);
break;
}
}
return 0;
}