题目大意:
用一个数组代表群山的高度。高度大的地方代表山峰,小的地方代表山谷。山谷可以容水。假设有一天下了大雨,求群山中总共可以容纳多少水?
如图所示情况,a代表该数组,总共可以容纳5个水。
解题思路:
初步想法可以枚举每一个单位,判断是否能放水。这种做法的复杂度为O(n^2*h)其中h为数组最大值,n为数组的大小。效率较低。
进一步观察发现:由于只有山谷可以存水,假设a[i],a[j]>a[k](i<k<j),那么i,j之间的水量可以直接算出,问题降解为两个子问题:求0到i的存水量和j到n-1的存水量
代码:
#include <iostream> #include <algorithm> #define maxn 1000 using namespace std; int hills[maxn]; int highest[maxn][maxn]; int highone[maxn][maxn]; int stones[maxn][maxn]; int total = 0; int n; int calWater(int f, int t) { //not yet implemented if (f+1==t) return 0; return (t-f-1)*min(hills[f], hills[t])-stones[f+1][t-1]; } void solve(int f, int t) { if (f >= t) return; int n1, n2; n1 = highone[f][t]; n2 = highest[f][n1-1] > highest[n1+1][n-1] ? highone[f][n1-1] : highone[n1+1][n-1];
if (n1 > n2) { swap(n1, n2); } total += calWater(n1, n2); solve(f, n1); solve(n2, t); } int main() { int i; cin >> n; for (i = 0; i < n; i++) { cin >> hills[i]; } for (i = 0; i < n; i++) { highest[i][i] = hills[i]; stones[i][i] = hills[i]; highone[i][i] = i; } int step = 2; int f,t,m; while (step <= n) { for (i = 0; i <= n-step; i++) { f = i; t = i+step-1; m = (f+t)/2; highest[i][i+step-1] = max(highest[i][m], highest[m+1][i+step-1]); highone[i][i+step-1] = highest[i][m] > highest[m+1][i+step-1] ? highone[i][m] : highone[m+1][i+step-1]; stones[i][i+step-1] = stones[i][m] + stones[m+1][i+step-1]; } step++; } solve(0, n-1); cout << total << endl; }
心得体会:
下面一行为吐槽请绕过。
{面试的时候被面试官问傻了(哭,连最简单的方法都没讲出来。唉,估计是终身遗憾了。不过下次面试应该会更轻松一些。要抓紧复习基础知识才行啊!}
这道题虽然简单但是用了分治的思想。没有想到更好的解法,希望有大神指点迷津!
更好的解法!(感谢@MchCyLh)
解题思路:见一楼评论
代码:
#include <iostream> #include <algorithm> #define maxn 1000 using namespace std; int a[1000]; int main() { int n, i; cin >> n; for (i = 0; i < n; i++) { cin >> a[i]; } int l, hl, r, hr, tot = 0; l = hl = 0; r = hr = n-1; while (r-l>1) { if (a[hl] < a[hr]) { i = ++l; while (i < r && a[i] <= a[hl]) { tot += a[hl]-a[i]; l++; i++; } if (i != n) { hl = i; } } else { i = --r; while (i > l && a[i] <= a[hr]) { tot += a[hr]-a[i]; r--; i--; } if (i != -1) { hr = i; } } } cout << tot << endl; }
复杂度降为O(n)www