6 5 1 4 1 6 1 7 2 7 2 8 3 0
4
这题一开始我没注意n的范围,结果写了个复杂度O(n^2),超时。其实这题类似那个数塔的题目,每个地点只能接左中右3个地方的馅饼,即一个塔的结点连接下面3个结点。又由于位置只有那11个,所以有很多都是重合的,故最多可以只用11个数字即可表达塔的一层。下面借一个网上的图来更直观的看一下。
用一个二维数组dp[i][j],i表示时间,j表示位置。于是,dp就表示i时间j位置时最大值,从底至上规划求出最大值。
#include<stdio.h> #include<string.h> int max(int i, int j) {return i > j ? i : j;} int a[100010][12]; int main() { int n, i, j, x, t; while(~scanf("%d", &n), n) { memset(a, 0, sizeof(a)); int last = 1; //记录最大时间 while(n--) { scanf("%d%d", &x,&t); a[t][x]++; //t为时间,x为位置 if(t > last) last = t; } for(i=last-1; i>=0; i--) { for(j=0; j<=10; j++) { if(j == 0) a[i][j] += max(a[i+1][j], a[i+1][j+1]); //边界考虑 else if(j == 10) a[i][j] += max(a[i+1][j], a[i+1][j-1]); else a[i][j] += max(a[i+1][j-1], max(a[i+1][j], a[i+1][j+1])); } } printf("%d\n", a[0][5]); //起点也就是当时间为0位置为5时有最大值 } return 0; }
当然代码可以改进一下,将所有位置都加1,即向右移,并且开始a数组全赋值为0,这样最大值的位置肯定是在1-11的范围内,避免了讨论边界情况。下面我一开始TLE的代码也纪念一下。
#include<cstdio> #include<algorithm> using namespace std; struct Node { int x, T; }p[100010]; bool cmp(Node c, Node d) {return c.T < d.T;} int main() { int n, i, j, dp[100010]; while(~scanf("%d", &n), n) { for(i=0; i<n; i++) scanf("%d%d", &p[i].x,&p[i].T); sort(p, p+n, cmp); int maxn = 0; for(i=0; i<n; i++) { dp[i] = 0; for(j=0; j<i; j++) { if(p[i].x >= p[j].x-1 && p[i].x <= p[j].x+1) dp[i] = max(dp[i], dp[j]+1); } if(dp[i] > maxn) maxn = dp[i]; } printf("%d\n", maxn); } return 0; }
唉,题目还是写的太少啊!!!