HDU 1176 免费馅饼
看到这题之后第一反应是数塔,但是和数塔有区别,数塔的时间间隔是看做1的,而这道题是不确定的。
题目的大概意思是:有m 个馅饼从天上掉下来,问最多能拿多少个馅饼。
首先,起点在5,每秒只能左 / 右移动一格。因此,第一秒的时候,可以到达的位置是4, 5, 6。第二秒是3, 4, 5, 6, 7。依次类推,直到可以到达0 ~ 10 所有位置。此后的步骤就和数塔类似了,只要注意时间T的变化就可以了。
手动模拟一下题目所给的测试数据:
6
5 1
4 1
6 1
7 2
7 2
8 3
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
先把数据按照时间从小到大的顺序进行一次排序,然后填入一个二维数组中(如上表)。
接下来,开始从0s的位置5开始进行DP。用0s 的5更新1s的4, 5, 6。得到下表:
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
接着用1s的4更新2s的3, 4, 5。(5和6以此类推更新),由于我要拿到最多的馅饼,所以我在更新的时候保留在当前时间当前位置所能拿到的馅饼的最大值。得到下表:
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 1 | 1 | 1 | 2 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
继续更新,得到下表:
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 1 | 1 | 1 | 2 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 1 | 3 | 3 | 3 | 4 | 0 | 0 |
最后遍历一趟3s的所有数据,输出其中的最大值即可,此处为4。
另外需要注意到是,这道题目的数据比较大,所以采用滚动数组的方式来进行存储,在利用滚动数组进行存储的时候,需要注意清除数据!否则会发生走到不可能走到的点这种错误,比如下面这组数据:
6
1 2
1 2
1 2
1 2
4 1
5 2
如果滚动数组的数据没有彻底清除,得到的结果会是4, 而不是2。
附AC代码:
1: #include <stdio.h>
2: #include <math.h>
3: #include <iostream>
4: #include <algorithm>
5: #include <string.h>
6: #include <stdlib.h>
7: #include <string>
8: #include <list>
9: #include <vector>
10: #include <map>
11: #define Clean(x) memset(x, 0, sizeof(x))
12: #define LL long long
13: using namespace std;
14:
15: typedef struct
16: {
17: int x, t;
18: }Piz;
19:
20: Piz buf[100009];
21:
22: int CMP(const Piz &a, const Piz &b)
23: {
24: return (a . t < b . t);
25: }
26:
27: int main()
28: {
29: int n;
30: int t[2][19];
31: while (~scanf("%d", &n) && n)
32: {
33: Clean(t);
34: for (int i = 1; i <= n; i++)
35: scanf("%d%d", &buf[i] . x, &buf[i] . t);
36: sort(buf + 1, buf + n + 1, CMP);
37: int T = 0;
38: for (int i = 1; i <= n; T++)
39: {
40: while (i <= n && buf[i] . t <= (T + 1))
41: {
42: t[(T + 1) % 2][buf[i] . x] += 1;
43: i++;
44: }
45: if (T <= 4)
46: {
47: for (int k = 4 - T; k <= 6 + T; k++)
48: {
49: int m = t[(T + 1) % 2][k] + t[T % 2][k];
50: if (k > 0)
51: m = max(m, t[(T + 1) % 2][k] + t[T % 2][k - 1]);
52: m = max(m, t[(T + 1) % 2][k] + t[T % 2][k + 1]);
53: t[(T + 1) % 2][k] = m;
54: }
55: for (int k = 0; k < 4 - T; k++) t[(T + 1) % 2][k] = 0;
56: for (int k = 7 + T; k <= 10; k++) t[(T + 1) % 2][k] = 0;
57: }
58: else
59: {
60: for (int k = 0; k <= 10; k++)
61: {
62: int m = t[(T + 1) % 2][k] + t[T % 2][k];
63: if (k > 0)
64: m = max(m, t[(T + 1) % 2][k] + t[T % 2][k - 1]);
65: m = max(m, t[(T + 1) % 2][k] + t[T % 2][k + 1]);
66: t[(T + 1) % 2][k] = m;
67: }
68: }
69: for (int k = 0; k <= 10; k++)
70: t[T % 2][k] = 0;
71: }
72: int res = t[T % 2][1];
73: for (int i = 2; i <= 10; i++)
74: res = max(res, t[T % 2][i]);
75: printf("%d\n", res);
76: }
77: return 0;
78: }
写的有点乱,凑合看吧Orz