广东工业大学第十三届景驰埃森哲杯程序设计竞赛

  1. 做第一题的时候一点思路都没有,看到第一眼就觉得应该用递归,因为我觉得是一种全排列,但是结果没做出来,最后队友用找规律的方法做了出来。
    而且有一个点的取值我也不理解,为什么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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值