Kick Ass(栈+模拟),递归

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;
}

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值