暑期OJ题解

7/13
洛谷P2437
题目描述 一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房 mmm 开始爬到蜂房 nnn,m<nm<nm<n,有多少种爬行路线?(备注:题面有误,右上角应为 n−1n-1n−1)在这里插入图片描述PS:此题我之前做过一摸一样的,通过找规律发现蜜蜂到达n点的时候有两种路线:一种是从a[n-2]到a[n],另一种是a[n-1]到a[n](这种情况以及包含了从a[n-2]到a[n-1]); 公式:a[n]=a[n-1]+a[n-2];
但是我发现在进行循环的时候程序运行停止了,才发现是数据太大的原因。如何毅然决然选择用大数去做。

#include<iostream>
#include<string>
using namespace std;
string Fibonaci[1000+5];          //本题是大数所以需要用字符串数组经行加法运算
string Fibonaci_num(const string&a,const string&b)
{
    int t=0,i;
    string c=a;                    //将a赋值给c(主要是让a的长度大小赋给c,以便计算)
        for(i=0;i<c.size();i++)
        {
          if(i<b.size())          //b的长度是小于a的长度
          {
            c[i]=(b[i]-'0'+a[i]-'0'+t)%10+'0';
            a[i]-'0'+b[i]-'0'+t<10?t=0:t=1;
          }
          else
          {
            c[i]=(a[i]-'0'+t)%10+'0';
            a[i]-'0'+t<10?t=0:t=1;
          }
        }
    if(t) c=c+'1';              //进1操作
    return c;
}
int main()
{
    int m,n;
    Fibonaci[0]="1";Fibonaci[1]="1";
    for(int i=2;i<=1000;i++)
      Fibonaci[i]=Fibonaci_num(Fibonaci[i-1],Fibonaci[i-2]);
    while(cin>>m>>n)
    {
        for(int i=Fibonaci[n-m].size()-1;i>=0;i--)
        cout<<Fibonaci[n-m][i];
        cout<<endl;
    }
    return 0;
}

***7/14号,今天做了一道递归题目,这题是通过蓝书上面一道题目思想而想出来的。
P1164 小A点菜
题目描述 不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩M元(M≤10000)。
餐馆虽低端,但是菜品种类不少,有N种(N≤100),第i种卖ai元(ai≤1000)。由于是很低端的餐馆,所以每种菜只有一份。
小A奉行“不把钱吃光不罢休”,所以他点单一定刚好吧uim身上所有钱花完。他想知道有多少种点菜方法。
由于小A肚子太饿,所以最多只能等待1秒
输入 #1
4 4
1 1 2 2
输出 #1
3
PS:这题问的是要有多少种情况 那么我们就要把选和不选的情况都考虑在内。
比如随便一道菜我可以选,也可以不选。如果选 那要考虑选了之后 我是否超过了总钱数。如果不选 那就跳过这道菜。按照这样的情况走下去直到等于或者超过总钱数,若超过则return,若没有超过sum++。

#include<iostream>
using namespace std;
int a[105],n,sum=0;
void order(int m,int num)
{
    if(num==0)  {sum++; return;} //退出条件
    else if(num<0) return;
    for(int i=m;i<=n;i++)
    {
        num-=a[i];               //选择a[i]这盘菜
        order(i+1,num);          //对下一盘菜进行同样选择
        num+=a[i];               //回溯不选
    }
}
int main()
{
    int sumnum;
    cin>>n>>sumnum;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    order(1,sumnum);
    cout<<sum;
    return 0;
}

思考:这题主要是利用函数递归一步一步去求解,把每一种情况都考虑到。每一道菜可以选也可以不选,让我想到了八皇后递归题目,我一开始想这题为什么会一个数组怎么会输出多行数,为什么会突然变了。这就是回溯的力量。


7/16号 今天做了一道题目P1873 是一到二分题目,题目容易读懂,基本思路也出来了,主要是题目看漏了一个地方。

#include<iostream>
#include<cstdio>
using namespace std;
long a[1000000+5];
long long m,n;
void Find_tree(long left,long right,const long long m)
{
    while(left<=right)
    {
      long long sum=0;
      long mid=left+(right-left)/2;
      for(int i=0;i<n;i++)
        if(a[i]>mid)
            sum+=a[i]-mid;
      /*if(sum==m) {cout<<mid;return;}*/       //为什么输出这个就错了(因为题目是要求你大于等于M而不是必须等于M)
      if(sum<m)
         right=mid-1;
      else
         left=mid+1;
    }
    cout<<left-1;                             //而这个却是对的?
}
int main()
{
    cin>>n>>m;
    long max=-1;
    for(long i=0;i<n;i++)
     {
         cin>>a[i];
         if(max<a[i]) max=a[i];
     }
    Find_tree(1,max,m);
}

PS:两个注释的地方就是错误所在,一直在wa不知道哪错了,后来看了题解才发现就那么小小的地方出现了错误,还是自己看题不太仔细啊!


洛谷P1223 接水问题
这道题以前做过类似的,具体想法如下:在一段数列A中,先将A从小到大排序:因为如果A[i]大于后面n个数,将A[i]和A[n+i]替换则n个人等待时间会减小(因为自身接水时间不算),按照局部解最优的情况下应该要时数列A从小到大排序在计算,这样才会总的等待时间最小。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef struct{
   int next,num;  //next 表示下标
}water;
water w[1000+5];
int cmp(const water&a,const water&b)
{
    return a.num<b.num;            //这里排序是如果相等,则下标保持不变
}
int main()
{
    int n;
    double sum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        w[i].next=i;
        cin>>w[i].num;
    }
    sort(w+1,w+n+1,cmp);
    int t=0;
    for(int i=1;i<=n;i++)
    {
        cout<<w[i].next<<" ";
        t+=w[i-1].num;          //注意这里是加上前一个的时间,而不是这个自己的时间
        sum+=t;
    }
    cout<<endl;
    printf("%.2lf",sum/n);
}

PS:这道题整体比较简单,做了一到水题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值