For a given cross-section diagram, reports areas of flooded sections.
Assume that rain is falling endlessly in the region and the water overflowing from the region is falling in the sea at the both sides. For example, for the above cross-section diagram, the rain will create floods which have areas of 4, 2, 1, 19 and 9 respectively.
Input
A string, which represents slopes and flatlands by \'/\', \'\\' and \'_\' respectively, is given in a line. For example, the region of the above example is given by a string "\\///\_/\/\\\\/_/\\///__\\\_\\/_\/_/\".
output
Report the areas of floods in the following format:
A
k L1 L2 ... Lk
In the first line, print the total area A of created floods.
In the second line, print the number of floods kk and areas Li(i=1,2,...,k) for each flood from the left side of the cross-section diagram. Print a space character before Li.
Constraints
-
1≤ length of the string ≤20,000
Sample Input 1
\\//
Sample Output 1
4
1 4
Sample Input 2
\\///\_/\/\\\\/_/\\///__\\\_\\/_\/_/\
Sample Output 2
35
5 4 2 1 19 9
题目大意:有一个堤坝上面有很多的坑,下了场雨把坑都填满了,问水的总面积和有几个水坑及每个水坑的面积。
解题思路:
1、明确每一个水坑是如何产生的,每有一对 \ / 就会产生一个一定长度的水层。类似数学运算的括号()
2、由数学运算就会自然地想到后缀表达式,就决定用栈来解决这个问题。
3、每次遇到一个 \ 就将它的坐标压入栈,等待遇到 / ,将 / 的坐标记录下。两个坐标之差就是单个水层的面积。
4、分隔与合并水坑,因为 \ 一定会产生在 / 的前面,所以可以用每个水坑第一个 \ 的坐标来表示水坑的位置,如果求得下一个水层的 \ 在某一个水坑的位置之前,就将这这个水坑与这个水层所在的水坑合并。
5、输出结果。
AC代码:
#include<bits/stdc++.h> using namespace std; //将每个 / 压入此栈 stack<int>s1; //将每个水坑压入此栈 stack<pair<int,int> >s2; char ch; int sum; int main(){ for(int i = 1;cin >> ch;i ++){ if(ch == \'\\\')s1.push(i);//注意下转义字符 else if(ch == \'/\' && (!s1.empty())){ int j = s1.top();s1.pop(); // i - j 代表了每一个水层的面积 sum += i - j; //判断该水层所在的水坑能否与之前的水坑合并 int a = i - j; while(!s2.empty() && s2.top().first > j){ a += s2.top().second; s2.pop(); } //将合并后的水坑压入栈 s2.push(make_pair(j,a)); } } //输出结果 vector<int>ans; while(!s2.empty()){ ans.push_back(s2.top().second); s2.pop(); } printf("%d\n%d",sum,ans.size()); for(vector<int>::iterator iter = ans.end()- 1;iter != ans.begin() - 1;iter --){ printf(" %d",*iter); } printf("\n"); return 0; }
做完此题的感受:
作为一名菜鸡,看到这道题的时候首先感到的是心有余而力不足,虽然想到的计算面积的方法差不多,但我一直在思考用队列记录每一个梯形(三角形)的底边长和高,然后写了60多行,发现后面水坑很难合并在一起,就一直卡在哪里,最后还是不得已看了题解,看完那题解简直是豁然开朗,选择正确的数据结构可以把复杂的问题如此优雅地解出来,我记得之前有人和我说过懂得数据结构的人和不知道数据结构的人写出来的是两种代码。我的老师之前告诉我算法和数据结构是相辅相成的,是不可分割的一部分,但是做完这道题我就感觉,数据结构可以更好得去理解算法,数据结构应该是比算法更加基础的。也在此表示一下现在正是踏上ACM这条不归路,希望自己以后的竞赛之旅也就像栈一样吧,能容纳旅途中的所有风景,并将它们不断地融合,继而遇见更加优秀的自己。