POJ 2563 - Demerit Points

http://poj.org/problem?id=2563

概要

運転免許を得た日付と、事故を起こしたときの日付およびそのときの点数が与えられる。 merit point が5になるまでの過程を出力する。

demerit point が無いとき、2年毎に merit point が1つ増える。 demerit point があるとき、1年毎に半分(切り捨て)になる。ただし、demerit が2以下のときは0になる。 ただし、事故を起こした場合はリセットされ、その時点から再び2年あるいは1年数える。

merit point が無いとき、事故を起こすと demerit point に点数が加算される。 merit point があるとき、事故を起こすと merit point の2倍の点数でキャンセルできる。

解法

やるだけ。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 static const int Y = 10000;
 6 
 7 void show(int d, int a)
 8 {
 9   printf("%d-%02d-%02d ", d/Y, (d%Y)/100, d%100);
10   if (a == 0) {
11     puts("No merit or demerit points.");
12   } else if (a < 0) {
13     printf("%d demerit point(s).\n", -a);
14   } else {
15     printf("%d merit point(s).\n", a);
16   }
17 }
18 
19 void merit(int& date, int& acc, int x)
20 {
21   while ((acc < 0 && date+Y <= x) || (acc >= 0 && acc < 5 && date+2*Y <= x)) {
22     if (acc < 0) {
23       acc = acc < -2 ? acc/2 : 0;
24       date += Y;
25     } else {
26       ++acc;
27       date += 2*Y;
28     }
29     show(date, acc);
30   }
31 }
32 
33 int main()
34 {
35   int date;
36   scanf("%d", &date);
37   int acc = 0;
38   show(date, acc);
39   for (int d, x; scanf("%d %d", &d, &x) != EOF;) {
40     merit(date, acc, d);
41     if (acc < 0) {
42       acc -= x;
43     } else if (2*acc <= x) {
44       acc = -x + 2*acc;
45     } else {
46       acc -= (x+1)/2;
47     }
48     date = d;
49     show(date, acc);
50   }
51   merit(date, acc, 100000000);
52   return 0;
53 }
poj/2563.cc