我最先看的是1176。
感觉自己做了一些dp题,有了些经验,就自己想了一会,敲了一份代码。
通过了样例,但是tle。
代码如下。
#include <stdio.h>
#include <math.h>
#include <string.h>
int dp[100000];
struct pie
{
int second;
int pos;
}pies[100000];
int main()
{
int n, m;
int i, j;
int now;
while (scanf("%d", &n) && n)
{
for (i = 1; i <= n; i++)
scanf("%d %d", &pies[i].pos, &pies[i].second);
memset(dp, 0, sizeof(dp));
pies[0].pos = 5;
pies[1].second = 1;
for (i = 1; i <= n; i++)
{
for (j = 0; j < i; j++)
{
if (abs(pies[i].pos - pies[j].pos) <= abs(pies[i].second - pies[j].second))
{
if (dp[j] + 1 > dp[i])
dp[i] = dp[j] + 1;
}
}
}
m = -1;
for (i = 1; i <= n; i++)
m = m > dp[i] ? m : dp[i];
printf("%d\n", m);
}
return 0;
}
然后开始找题解。
发现这竟然是一道二维的dp。同时找到了 2084 这道题(数塔)。
思路也比较好理解。
AC代码如下。
#include <stdio.h>
#include <string.h>
// 0 1 2 3 4 5 6 7 8 9 10 11 12
int time[100001][13]; // _ 0 1 2 3 4 5 6 7 8 9 10 _
int max(int a, int b, int c)
{
a = a > b ? a : b;
a = a > c ? a : c;
return a;
}
int main()
{
int n;
int x, T;
int i, j;
int t;
while (scanf("%d", &n) && n)
{
memset(time, 0, sizeof(time));
t = -1;
for (i = 1; i <= n; i++)
{
scanf("%d %d", &x, &T);
x++;
time[T][x]++;
t = t > T ? t : T;
}
for (i = t - 1; i >= 0; i--)
{
for (j = 1; j <= 11; j++)
time[i][j] += max(time[i + 1][j - 1], time[i + 1][j], time[i + 1][j + 1]);
}
printf("%d\n", time[0][6]);
}
return 0;
}
这道题有一些问题。
time[100000][13] WA
time[100001][13] AC
但是题中给定的条件是
0<n<100000
0<T<100000
T最大是99999。
然后是2084数塔这道题。
一次AC。
#include <stdio.h>
int map[101][101];
int max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
int C;
int N;
int i, j;
scanf("%d", &C);
while (C--)
{
scanf("%d", &N);
for (i = 1; i <= N; i++)
{
for (j = 1; j <= i; j++)
scanf("%d", &map[i][j]);
}
for (i = N - 1; i >= 1; i--)
{
for (j = 1; j <= i; j++)
{
map[i][j] += max(map[i + 1][j], map[i + 1][j + 1]);
}
}
printf("%d\n", map[1][1]);
}
return 0;
}
上面的代码是自下而上dp的。
开了个脑洞,自上而下是否可以呢?
证明也可以。下面是AC代码。
#include <stdio.h>
int map[101][101];
int max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
int C;
int N;
int i, j;
int m;
scanf("%d", &C);
while (C--)
{
scanf("%d", &N);
for (i = 1; i <= N; i++)
{
for (j = 1; j <= i; j++)
scanf("%d", &map[i][j]);
}
for (i = 2; i <= N; i++)
{
map[i][1] += map[i - 1][1];
for (j = 2; j <= i; j++)
{
map[i][j] += max(map[i - 1][j], map[i - 1][j - 1]);
}
}
m = -1;
for (i = 1; i <= N; i++)
m = m > map[N][i] ? m : map[N][i];
printf("%d\n", m);
}
return 0;
}
这题看起来更像是一个二维dp的特殊情况。
还有一个问题。1176馅饼那道题是否也可以自上而下dp呢(上面的代码是自下而上dp的)?
我认为是不可以。
因为题目中规定了起点5。自上而下的话,不能保证最大值的起点是5。
而数塔那道题只有一个起点。