- 做第一题的时候一点思路都没有,看到第一眼就觉得应该用递归,因为我觉得是一种全排列,但是结果没做出来,最后队友用找规律的方法做了出来。
而且有一个点的取值我也不理解,为什么0级台阶时有一种跳法。其实这是个数学问题,类似于c(0,0) = 1, 从0个中取0个,有一种实现的方法,就是一个也不取。
代码如下:
#include<iostream>
using namespace std;
int main()
{
int sum[35];
int i;
int t;
int n;
sum[0]=1;
sum[1] = 1;
sum[2] = 2;
sum[3] = 4;
for(i=4;i<31;i++)
{
sum[i]=0;
for(int j=0;j<i;j++)
{
sum[i]+=sum[j];
}
}
cin>>t;
for(i=0;i<t;i++)
{
cin>>n;
cout<<sum[n]<<endl;
}
return 0;
}
但是我第一个思路是使用递归来做,结果导致超时了,递归代码如下:
#include<iostream>
using namespace std;
int calc(int n,int k)
{
if(k==n)return 1;
if(k>n)return 0;
int s=0;
for(int i=1;i<=n;i++)
{
s+= calc(n,k+i);
}
return s;
}
int main()
{
int n;
int t;
cin>>t;
for(int i=0;i<t;i++)
{
cin>>n;
int s;
if(n==0) s = 1;
else s = calc(n,0);
cout<<s<<endl;
}
return 0;
}
关于递归的一点思考:
最近做蓝桥杯,很多题都想使用递归来做,但是没有考虑到复杂度的问题,结果可能会导致超时或者爆栈,这是使用递归必须要注意的。
例如本体如果使用递归求解,复杂度为 n + n的2次方 +n的三次方 …+ n的n次方。假如 n为30,肯定会超时。
c. 平分游戏
d. psd面试
这题从一开始我就没读懂题目的意思,根本没有区分开最长回文子序列和最长回文子串的区别,建议不懂得旁友也赶紧区分一下。
最长回文子串一定是连续的一个串,而最长回文子序列则不需要是一整个串,例如 “abc,ba” 的最长回文子串的长度是1,而最长回文子序列的长度是 5. (abcba) 最长回文子序列可以删除不回文的字符。
求最长回文子序列有两种做法
1.递归
#include<iostream>
#include<string>
#include<cctype>
using namespace std;
int maxn(int a,int b)
{
return a>b?a:b;
}
int calc(string s,int begins,int ends)
{
int i;
int sum=0;
if(begins ==ends)
{
return 1;
}
if(begins>ends)
{
return 0;
}
if(s[begins] == s[ends])
{
sum = calc(s,begins+1,ends-1)+2;
}
else
{
sum = maxn( calc(s,begins+1,ends),calc(s,begins,ends-1) );
}
return sum;
}
int main()
{
string s;
string temp;
int i;
while(cin>>s)
{
temp ="";
for(i=0;i<s.length();i++)
{
if(isalpha(s[i]))
{
temp+=tolower(s[i]);
}
else temp+=s[i];
}
// cout<<temp<<endl;
int sum = calc(temp,0,temp.length()-1);
cout<<temp.length() - sum<<endl;
}
return 0;
}
以上,没错 我拿去交了以后又T了,让我们来看看这段代码的复杂度,如果字符串的长度为 1000 ,那么使用递归的方法则时间复杂度为 1+2的2次方+2的三次方+。。。2的400次方+。。。
总之就是指数爆炸叠加增长,蓝桥杯坑我,为啥老让我写递归,明明这么慢。
第二种方法 动态规划
我对动态规划不太熟,一星期以前刚做了第一道动态规划的题目。
然后在网上找了讲dp求子序列的代码
大致思想和递归是差不多的。
if string[i] = string[j] dp[i][j] = dp[i+1][j-1];
else dp[i][j] = max (dp[i][j-1],dp[i+1][j]);
当 i<=j 的时候,上式成立。且当 i == j的时候 dp[i][i] =1;
而且 i的变化方向 必须是从大到小,j的方向必须是从小到大。
这是由上述方程决定的。 dp的复杂度为 (n的平方)
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
int max2(int a,int b)
{
return a>b?a:b;
}
int calc(string s)
{
int i,j;
int length = s.length();
int n=length;
vector<vector<int> > dp(length,vector<int>(n));
for(i=0;i<length;i++)
{
// memset(dp[i],0,sizeof(dp[i]));
dp[i][i] =1;
}
for(i=length -1;i>=0;i--)
{
for(j=i+1;j<length;j++)
{
if(s[i]==s[j]) dp[i][j] = dp[i+1][j-1]+2;
else dp[i][j] =max2(dp[i+1][j],dp[i][j-1]);
}
}
return dp[0][length-1];
}
int main()
{
string s;
string temp;
while(cin>>s){
temp ="";
for(int i=0;i<s.length();i++)
{
if(isalpha(s[i]))
{
temp+=tolower(s[i]);
}
else temp +=s[i];
}
//cout<<temp<<endl;
int sum =calc(temp);
cout<<s.lenth()-sum<<endl;
}
return 0;
}