正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!左边有个“赞”字,你就顺手把它点了吧
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(从24开始,在1结束)。当然25-24-23 - … - 3 ― 2 ― 1更长。事实上,这是最长的一条。
输入的第一行为表示区域的二维数组的行数R和列数C(1≤R,C≤100)。下面是R行,每行有C个数,代表高度(两个数字之间用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
典型bfs
评测记录 52ms / 2085KB
虽然本题数据很水,但是我们还是需要用BFS+记忆化,否则会TLE好几个点
先从样例入手。样例的解显然是从(3, 3)
的25开始,按照红线的顺序,到(1, 1)
的1,总长度为25。
题目要求最优解,所以我们必须把所有可能的情况都枚举出来!我们用变量ans来记录最优解。
我们将会枚举整个地图的每个点。当然,这是不可行的。因为如果你直接这样做,那么最坏情况时间复杂度将是O(nm*nm),显然会超时。所以,我们必须使用记忆化搜索,那么时间复杂度会降低为O(nm)。
我们用mp来存储整个地图,用f来存储每个点能滑的最大长度。由于要枚举每一个点的情况,那么我们使用双层循环。每次循环,我们用ans=max{ans + f[i][j]}
求出到目前为止最长的长度。最后输出即可。
我们来看看整个程序的核心:void bfs(int x, int y)
。这里用一个结构体POINT来表示地图上一个点的x轴与y轴,以及从起点(i, j)
到当前点的距离n。这里为了方便起见,使用STL的单向队列。如果有兴趣的朋友还可以尝试手写队列。
当然,滑雪是不能滑到地图外面的!所以,我们应加上条件判断,若有以下任意一种情况则用continue跳过本次循环:pos.x<1
、pos.y<1
、pos.x>n
和pos.y>m
。这是边界判断。
然后,我们得判断当前这个点是否已经被搜过!这也是记忆化搜索的核心。由于在之前我们已经将f全部赋值为INF了,所以要判断是否被搜过,我们只需判断f[i][j]!=INF
的情况,那样,我们就只需将搜过的数据f[i][j]
拿来直接用就行了。在这把临时变量b
赋值为true,由于已经搜过了,就不必再搜一次了,将f[i][j]
赋值为当前最优解后,如果b为true,那么我们直接可以跳过本次循环,因为已经搜过了。
后面,四行代码,就是分别向上下左右扩展,向队列里push元素,下一次循环时遍历。这里的if就是条件判断:新的点的值是否小于当前点的值,因为根据牛顿万有引力定律,只能向下滑。
于是很愉快地AC了…
#include
#include
using namespace std;
#define max(a, b) (((a)>(b))?(a):(b))
#define INF -2147483648
struct POINT {
int x;
int y;
int n;
};
int n, m;
int mp[110][110];
int f[110][110];
POINT point(int x, int y, int n) {
POINT pos;
pos.x = x;
pos.y = y;
pos.n = n;
return pos;
}
void bfs(int x, int y) {
queue q;
q.push(point(x, y, 1));
while(!q.empty()) {
POINT pos = q.front(); q.pop();
if(pos.x < 1 || pos.y < 1 || pos.x > n || pos.y > m) continue;
bool b = false;
if(f[pos.x][pos.y] != INF) pos.n += f[pos.x][pos.y]-1, b = true;
if(pos.n > f[x][y]) f[x][y] = pos.n;
if(b == true) continue;
if(mp[pos.x][pos.y] > mp[pos.x+1][pos.y]) q.push(point(pos.x+1, pos.y, pos.n+1));
if(mp[pos.x][pos.y] > mp[pos.x][pos.y+1]) q.push(point(pos.x, pos.y+1, pos.n+1));
if(mp[pos.x][pos.y] > mp[pos.x-1][pos.y]) q.push(point(pos.x-1, pos.y, pos.n+1));
if(mp[pos.x][pos.y] > mp[pos.x][pos.y-1]) q.push(point(pos.x, pos.y-1, pos.n+1));
}
}
int main() {
int ans = 0;
cin >> n >> m;
for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) cin >> mp[i][j], f[i][j] = INF;
for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) bfs(i, j), ans = max(ans, f[i][j]);
cout << ans;
return 0;
}