Kick Ass
题目描述
你玩过一个叫做"Kick Ass - Destroy the web"的游戏吗?你没有玩过也没关系,这个游戏是通过js来加载一个飞船,让你可以通过控制它发射子弹来摧毁网页上的元素,从而获得分数。我们知道HTML是超文本标记语言,简单地说就是通过一些标签来指明元素的展示方式,比如<p></p>就可用作表明这是一个段落,<div></div>表明这是一个区块。假设有一个网页只含有<p></p>、<div></div>两种标记,其中<p><p>中只含有数字,摧毁<p></p>标记可获得其中各个数字之和的分数,摧毁<div></div>可获得其中包含的所有<p></p>分数与包含的<div></div>分数二倍之和的分数。现在给你一个网页,你能否计算出完全摧毁它可得到的分数。
为了简化难度,你可以假设:所给网页的字符只有数字和标签所给网页的标签都正确匹配保证所给网页中的数字都在<p></p>标签内<p></p>标签内不会含有标签<div></div>标签内可能含有<p></p>标签和<div></div>标签
输入
多组测试数据,请处理到文件结束。每组占一行,有一个长度不大于1000的字符串代表所给网页。
输出
请输出完全摧毁此网页可获得的分数。
样例输入
<div><p>123</p><div><p>123</p></div></div>
样例输出
18
下面是AC代码
#include<cstdio> //本题用栈或dfs解决时其实都用到了递归的思想
#include<cstring>
#include<stack>
using namespace std;
char str[11000];
int main()
{
while(~scanf("%s",str)){
stack<int> s;
int flag = 0,ans = 0,sum = 0; //flag表示有多少个<div>,用来判断乘多少次2,ans是中间变量,sum用来计算最后栈里各元素之和
int len = strlen(str);
for(int i = 0;i<len;i++){
if(str[i] == '<' && str[i+1] == 'd'){//当遇到<div>时,让flag自加1,并用-1在这标记一下,让-1标记的目的是,比如-1 -1 3 -1(在栈中不会出现,这里为了方便说明) 4 -1(在栈中不会出现),计算结果应为(3*2+4)*2
flag++;
s.push(-1);
}
else if(str[i] == '<' && str[i+1] == '/' && str[i+2] == 'd'){//遇见</div>时,它和之前的那个<div>中间的值都会乘2,即到之前标记的最近的那个-1处中的数
while(!s.empty() && s.top() != -1){
ans += s.top(); //计算该区间中的值后再判断是否乘2
s.pop();
}
s.pop(); //弹出一个-1
flag--; //注意题目中的这句话:摧毁<div></div>可获得其中包含的所有<p></p>分数与包含的<div></div>分数二倍之和的分数(可以看出最外层的<div></div>不会使结果乘2,所以要让flag先自减1)
if(flag) s.push(ans*2);
else s.push(ans); //若为0直接压进栈
ans = 0;
}
else if(str[i] == '<' && str[i+1] == 'p' ){// <p></p>的是直接相加,就很好理解了
i += 3;
while(str[i] != '<'){
ans += str[i] - '0';
i++;
}
s.push(ans);
ans = 0;
}
}
while(!s.empty()){ //计算最后的结果
sum += s.top();
s.pop();
}
printf("%d\n",sum);
}
return 0;
}