习题日常第一练

今日习题

1栈(题目链接

这个题是个思维题,可能一开始会想到找规律,但是发现这个序列可以从每俩个数字中间拆开成为这俩个序列的组合,就是个复杂一点的递推,看题解以后发现这就是卡特兰数,代码如下。

 #include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#define ll long long int
const int mod=1e9+7;
using namespace std;
string s,s1;
ll a[202000];
int main()
{
    ios::sync_with_stdio(false);
    ll n,k,i,j,m=0,sum=0,pi,ans=-0x3f3f3f3f;
    cin>>n;
    a[0]=1;
    a[1]=1;
    for(i=2;i<=n;i++)
    {
        for(j=0;j<i;j++)
        {
            a[i]+=a[j]*a[i-j-1];
        }
    }
    cout<<a[n];
  return 0;
}

2开心的金明(题目链接

这个题是个简单的动态规划,类似于01背包问题,每个物品的价值可直接认为已知价值乘以重要度,具体见代码如下。

#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#define ll long long int
const int mod=1e9+7;
using namespace std;
struct node
{
    int v,w;
}a[20010];
int b[30010];
int main()
{
    ios::sync_with_stdio(false);
    ll n,k,i,j,m=0,sum=0,pi,ans=-0x3f3f3f3f,id;
    cin>>m>>n;
    for(i=0;i<n;i++)
    {
        cin>>a[i].v>>a[i].w;
        a[i].w*=a[i].v;
    }
    for(i=0;i<n;i++)
    {
        for(j=m;j>=0;j--)
        {
            if(j>a[i].v)
            {
               b[j]=max(b[j],b[j-a[i].v]+a[i].w);
            }
        }
    }
    cout<<b[m];
  return 0;
}

3多项式输出(题目链接

这个题乍一看特别水,我之所以感觉应该写一下的原因是我wa了好几发,这个题让我更加注意细节,以免在比赛场上出现这种问题搞自己心态,对于正负号以及负一和一的处理,代码如下(比较lj)。

#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
#define ll long long int
const int mod=1e9+7;
using namespace std;
int b[30010];
int main()
{
    ios::sync_with_stdio(false);
    ll n,k,i,j,m=0,sum=0,pi,ans=-0x3f3f3f3f,id;
    cin>>n;
    for(i=0;i<=n;i++)
    {
        cin>>b[i];
    }
     j=n-1;
     if(abs(b[0])!=1)
        cout<<b[0]<<"x"<<"^"<<n;
        else
        {
           if(b[0]>0)
            cout<<"x"<<"^"<<n;
            else if(b[0]<0)
                cout<<"-"<<"x"<<"^"<<n;
        }
    for(i=1;i<n-1;i++)
    {
        if(b[i]>0&&b[i]!=1)
        {
            cout<<"+"<<b[i]<<"x"<<"^"<<j;

        }
        else if(b[i]<0&&b[i]!=-1)
        {
            cout<<b[i]<<"x"<<"^"<<j;
        }
        else
        {
            if(b[i]==1)
            {
                 cout<<"+"<<"x"<<"^"<<j;
            }
            else if(b[i]==-1)
            {
                cout<<"-"<<"x"<<"^"<<j;
            }
        }
        j--;
    }
    if(b[n-1]>0&&b[n-1]!=1)
    {
        cout<<"+"<<b[n-1]<<"x";
    }
    else if(b[n-1]<0&&b[n-1]!=-1)
    {
        cout<<b[n-1]<<"x";
    }
    else
    {
        if(b[n-1]>0)
            cout<<"+"<<"x";
        else if(b[n-1]<0)
            cout<<"-"<<"x";
    }
     if(b[n]>0)
        {
            cout<<"+"<<b[n];

        }
        else if(b[n]<0)
        {
            cout<<b[n];
        }
        /*else
        {
            if(b[n]==1)
                 cout<<"+"<<"x";
            else if(b[n]==-1)
                cout<<"-x";
        }*/
  return 0;
}

4石子合并(题目链接

这个题是个经典的三维动态规划,不得不说,确实有时候数据范围也会提示你应该朝哪个时间复杂度的算法去想。本题的石子排列是一个环形,我们在数组中可以通过将已知石子排列增长为原来二倍,将原本的头和尾相接,将石子序列复制一遍,最后处理的时候从头遍历一遍原本的石子序列长度的区间即可。首先求前缀和,然后对于每个区间,可以被中间的任意一个位置分割为两个区间,假设这俩个区间的花费已知,则所求区间等于这俩个区间花费之和加上这个区间每个石头的花费,每个区间能被以此类推分为若干个,求其最大值(最小值)即可。具体代码如下。

#include<cmath>
#include <iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<math.h>
#include<stack>
#include<algorithm>
#include<queue>
#include<bitset>
using namespace std;
int dp[610][610],a[1010],sum[1010];
int main()
{
    ios::sync_with_stdio(false);
    int n,m,i,j,k;
    memset(dp,0x3f,sizeof(dp));
    memset(sum,0,sizeof(sum));
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=a[i]+sum[i-1];
        dp[i][i]=0;
    }
    for(i=n+1;i<=2*n;i++)
    sum[i]=a[i-n]+sum[i-1],dp[i][i]=0;
    for(k=1;k<=2*n;k++)
      for(i=k;i>0;i--)
    {
        for(j=i;j<k;j++)
        {
            if(i==k)
            dp[i][k]=0;
           else
          dp[i][k]=min(dp[i][k],dp[j+1][k]+dp[i][j]+sum[k]-sum[i-1]);
        }
    }
    int ans=0x3f3f3f3f;
    for(i=1;i<=n;i++)
        ans=min(dp[i][i+n-1],ans);
    for(i=0;i<401;i++)
        for(j=0;j<401;j++)
        dp[i][j]=0;
    for(k=1;k<=2*n;k++)
      for(i=k;i>0;i--)
    {
        for(j=i;j<k;j++)
        {
            if(i==k)
            dp[i][k]=0;
           else
          dp[i][k]=max(dp[i][k],dp[j+1][k]+dp[i][j]+sum[k]-sum[i-1]);
        }
    }
    int aps=-1;
     for(i=1;i<=n-1;i++)
        aps=max(dp[i][i+n-1],aps);
        cout<<ans<<endl<<aps;
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值