skiing
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
-
输入
-
第一行表示有几组测试数据,输入的第二行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
后面是下一组数据;
输出
- 输出最长区域的长度。 样例输入
-
1 5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
样例输出
25
自己用dfs做了一下,提交总是WA。
不对,,,刚无聊又看了下代码,删掉了一些没用的语句,交上去试了试竟然AC了。。。。
??? 在南阳OJ上Ac了, 再提交到百炼上Time Limit EXCEED。。。。。。看来南阳的测试数据和北大比还是有差距。
#include <iostream> #include <algorithm> #include <cstring> using namespace std; void dfs(int x, int y); int a[110][110]; int N; int counter; int maxCounter; int visited[110][110]; int dir[4][2] = {{1,0},{0,1},{-1,0}, {0,-1}}; int R, C; int main() { cin >> N; while(N--){ maxCounter = 0; memset(a, 0, sizeof(a)); memset(visited, 0, sizeof(visited)); counter = 1; cin >> R >> C; for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ cin >> a[i][j]; } } for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ counter = 1; dfs(i, j); } } maxCounter = max(maxCounter, counter); cout << maxCounter << endl; } return 0; } void dfs(int x, int y) { for(int i=0; i<4; ++i){ int sx, sy; sx = x + dir[i][0]; sy = y + dir[i][1]; if(sx <0 || sx >= R || sy <0 || sy >= C) continue; if(!visited[sx][sy] && a[sx][sy] < a[x][y]){ visited[sx][sy] = visited[x][y] + 1; ++counter; maxCounter = max(maxCounter, counter); dfs(sx,sy); visited[sx][sy] = 0; --counter; } } }
上面dfs中将图中每个结点都dfs一遍时间复杂度实在有点高,测试数据厉害一点的话肯定会超时,所以再网上看看动态规划怎么写
-
看了下Mooc郭炜老师讲的,自己写了个“我为人人”的动规,耗时1007ms, 百炼上这道题时间限制在1000ms(南阳3000ms),还是超时
-
#include <iostream> #include <algorithm> #include <cstring> using namespace std; void dfs(int x, int y); int a[110][110]; int N; int counter; int maxCounter; int visited[110][110]; int dir[4][2] = {{1,0},{0,1},{-1,0}, {0,-1}}; int R, C; void dp(int x, int y); int main() { cin >> N; while(N--){ maxCounter = 1; memset(a, 0, sizeof(a)); counter = 1; cin >> R >> C; for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ cin >> a[i][j]; visited[i][j] = 1; } } for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ if(visited[i][j] == 1){ dp(i, j); } } } cout << maxCounter << endl; } return 0; } void dp(int x, int y) { for(int i=0; i<4; ++i){ int sx = x + dir[i][0]; int sy = y + dir[i][1]; if(sx <0 || sx >= R || sy <0 || sy >= C) continue; if( a[sx][sy] > a[x][y]){ visited[sx][sy] = max(visited[sx][sy], visited[x][y]+1); maxCounter = max(maxCounter, visited[sx][sy]); dp(sx,sy); } } }
还是看看网上大神写的“人人为我”型动规怎么写 -
-
#include <iostream> #include <algorithm> #include <cstring> using namespace std; int a[110][110]; int N; int maxCounter; int dp[110][110]; int dir[4][2] = {{1,0},{0,1},{-1,0}, {0,-1}}; int R, C; int dfs(int x, int y); int main() { cin >> N; while(N--){ memset(dp, -1, sizeof(dp)); maxCounter = 0; cin >> R >> C; for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ cin >> a[i][j]; } } for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ maxCounter = max(maxCounter, dfs(i, j)); } } for(int i=0; i<R; ++i){ for(int j=0; j<C; ++j){ cout << dp[i][j] << ' '; } cout << endl; } cout << maxCounter << endl; } return 0; } int dfs(int x, int y) { if(dp[x][y] != -1) return dp[x][y]; int maxStep = 0; for(int i=0; i<4; ++i){ int sx = x + dir[i][0]; int sy = y + dir[i][1]; if(sx < 0 || sx >= R || sy < 0 || sy>= C) continue; if(a[sx][sy] < a[x][y]){ dp[sx][sy] = dfs(sx, sy); maxStep = max(maxStep, dp[sx][sy]); } } dp[x][y] = maxStep + 1; return dp[x][y]; }
提交到百炼上 耗时4ms AC -
-
第一行表示有几组测试数据,输入的第二行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。