A 新·神魔之井
题目链接:http://acm.buaa.edu.cn/problem/719/
解题分析
鉴于是上学期的陈题,没什么过多可以说的,具体内容请查询“角谷猜想”。
此外,原本想考察一个叫“阿克曼函数”的递归函数,但是由于该函数在时间与数值上的增长率都十分迅猛,因此没有设题,有兴趣练习一下的同学可以自行查阅并练习一下。
参考代码
//by trashLHC
#include<iostream>
using namespace std;
int cube(int n)
{
if(n==1) return 0;
else if(n%2==0) return 1+cube(n/2);
else return 1+cube(n*3+1);
}
int main()
{
int n;
while(cin>>n)
cout<<cube(n)<<endl;
return 0;
}
B AString.h(III)
题目链接:http://acm.buaa.edu.cn/problem/901/
解题分析
本题为递归(或者非递归)与字符串处理的双重结合,处理方式较为巧妙。
下面介绍递归版的算法。
既然是递归,那么首先要做的,是从大问题中提炼等价的小问题。
来看下面的一个字符串
3(a2(bc))
不难看出3(….)与2(….)实际上要解决的问题是完全相同的。
因此子问题找到,第一个要解决的问题搞定。
接下来就是要看子问题应该如何解决了。
从上面的可以看出,进入下一级子问题的标志是出现一个数字。(如果出现abc3(def)这样的,可以当做1(abc3(def))处理)
因此每一次递归首先要做的是将位于字段首端的数字拆解出来,拆解方法之前的上机题中经常出现,相信大家都知道了,这里不作赘述,实在不会的研读代码解决。
然后碰到左括号或者字母(由于会出现2st—>sst这种情况)
如果碰到字母,假设数字为num,那么将这个字母直接输出num次就好了。
如果碰到左括号,嗯,括号里面的是一个子问题,进入递归,并且这个递归执行num次。
而如果遇到右括号,则返回当前下标位置,以便上一层递归跳过这一段子问题继续之后的过程。
具体参见代码。
此外,附带了由Jeffrey提供的非递归版代码,用栈实现,大家可以研究研究。
参考代码
//by trashLHC
//recursive version
#include<iostream>
#include<cstdio>
using namespace std;
string s;
int solve(int i){
int num,tmp;
for(;i<s.length()&&s[i]!=')';i++){
for(num=0;s[i]>='0'&&s[i]<='9';i++)
num=num*10+s[i]-'0';
if(!num) num=1;
if(s[i]=='('){
for(int j=0;j<num;j++)
tmp=solve(i+1);
i=tmp;
}
else{
for(int j=0;j<num;j++)
printf("%c",s[i]);
}
}
if(s[i]==')') return i;
}
int main(){
while(cin>>s){
solve(0);
printf("\n");
s.clear();
}
return 0;
}
//by wjfwzzc
//non-recursive version
#include<iostream>
#include<string>
#include<cctype>
#include<stack>
using namespace std;
stack<pair<string,int> > s;
int main()
{
string str;
while(cin>>str)
{
string ans="";
for(int i=0; i<str.size(); ++i)
{
if(str[i]==')')
{
pair<string,int> top=s.top();
s.pop();
string tmp=ans;
while(--top.second)
ans+=tmp;
ans=top.first+ans;
continue;
}
int num=0;
for(; isdigit(str[i]); ++i)
num=num*10+str[i]-'0';
if(num==0)
++num;
if(str[i]=='(')
{
s.push(make_pair(ans,num));
ans="";
continue;
}
while(num--)
ans+=str[i];
}
while