百度2017春招笔试真题编程题集合题解

百度2017春招笔试真题编程题集合题解

【题1】

在这里插入图片描述

【解题思路】

水题,随便写写

【AC代码】

#include <iostream>
#include <algorithm>
using namespace std;
int a[55];
bool vis[1100];
int main(){
    int n;
    scanf("%d",&n);
    int k=0;
    for(int i=1;i<=n;++i){
        int x;
        scanf("%d",&x);
        if(!vis[x]){
            a[++k]=x;
            vis[x]=true;
        }
    }
    if(k<3){
        puts("-1");
        return 0;
    }
    sort(a+1,a+k+1);
    printf("%d\n",a[3]);
    return 0;
}

【题2】

在这里插入图片描述

【解题思路】

暴力枚举每个点被去除的情况,找到最优解

【AC代码】

#include <bits/stdc++.h>
#define min(a,b) (a)>(b)?(b):(a)
int a[55];
int main(){
    int n;
    scanf("%d",&n);
    int sum=0;
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        sum+=abs(a[i]-a[i-1]);
    }
    sum-=abs(a[1]);
    int ans=0x3f3f3f3f;
    for(int i=2;i<n;++i){
        ans=min(ans,(sum-(abs(a[i]-a[i-1])+abs(a[i+1]-a[i]))+abs(a[i+1]-a[i-1])));
    }
    printf("%d\n",ans);
    return 0;
}

【题3】

在这里插入图片描述

【解题思路】

水题,有很多情况数据没卡,比如共线,点重合等情况,暴力枚举+海伦公式

【AC代码】

#include <bits/stdc++.h>
#define max(a,b) (a)<(b)?(b):(a)
#define eps 1e-6
using namespace std;
typedef long long ll;
struct point{
    double x,y,z;
    inline point(){}
    inline point(double mx,double my,double mz):x(mx),y(my),z(mz){}
    inline bool operator == (const point& b){return x==b.x&&y==b.y&&z==b.z;}  //共点
}R[55],G[55],B[55];
inline double cal(const point& a,const point& b){
    ll x=(a.x-b.x)*(a.x-b.x);
    ll y=(a.y-b.y)*(a.y-b.y);
    ll z=(a.z-b.z)*(a.z-b.z);
    ll d=x+y+z;
    return (double)sqrt(d);
}
inline bool judge(const point& a,const point& b,const point& c){  //共线
    return (ll(a.y-b.y)*ll(a.z-c.z)-ll(a.y-c.y)*ll(a.z-b.z)<=eps)&&(ll(a.x-b.x)*ll(a.y-c.y)-ll(a.x-c.x)*ll(a.y-b.y)<=eps)&&(ll(a.x-b.x)*ll(a.z-c.z)-ll(a.x-c.x)*ll(a.z-b.z)<=eps);
}
int main(){
    int n;
    scanf("%d",&n);
    int r=0,g=0,b=0;
    for(int i=1;i<=n;++i){
        char c;
        double x,y,z;
        scanf(" %c %lf%lf%lf",&c,&x,&y,&z);
        switch(c){
            case 'R':
                R[++r]=point(x,y,z);
                break;
            case 'G':
                G[++g]=point(x,y,z);
                break;
            case 'B':
                B[++b]=point(x,y,z);
                break;
            default:break;
        }
    }
    double ans=0.0;
    if(r>=3)  //同为RED
    for(int i=1;i<=r;++i){
        for(int j=1;j<=r;++j){
            for(int k=1;k<=r;++k){
                if(R[i]==R[j]||R[i]==R[k]||R[j]==R[k]||judge(R[i],R[j],R[k])) continue;
                    double a=cal(R[i],R[j]);
                    double b=cal(R[i],R[k]);
                    double c=cal(R[j],R[k]);
                    if(a>(b+c)||b>(a+c)||c>(a+b)) continue;
                    double d=(a+b+c)/2;
                    double temp=sqrt(d*(d-a)*(d-b)*(d-c));
                    ans=max(ans,temp);
            }
        }
    }
    if(g>=3)  //同为GREEN
    for(int i=1;i<=g;++i){
        for(int j=1;j<=g;++j){
            for(int k=1;k<=g;++k){
                if(G[i]==G[j]||G[i]==G[k]||G[j]==G[k]||judge(G[i],G[j],G[k])) continue;
                    double a=cal(G[i],G[j]);
                    double b=cal(G[i],G[k]);
                    double c=cal(G[j],G[k]);
                    if(a>(b+c)||b>(a+c)||c>(a+b)) continue;
                    double d=(a+b+c)/2;
                    double temp=sqrt(d*(d-a)*(d-b)*(d-c));
                    ans=max(ans,temp);
            }
        }
    }
    if(b>=3) //同为BLUE
    for(int i=1;i<=b;++i){
        for(int j=1;j<=b;++j){
            for(int k=1;k<=b;++k){
                if(B[i]==B[j]||B[i]==B[k]||B[j]==B[k]||judge(B[i],B[j],B[k])) continue;
                    double a=cal(B[i],B[j]);
                    double b=cal(B[i],B[k]);
                    double c=cal(B[j],B[k]);
                    if(a>(b+c)||b>(a+c)||c>(a+b)) continue;
                    double d=(a+b+c)/2;
                    double temp=sqrt(d*(d-a)*(d-b)*(d-c));
                    ans=max(ans,temp);
            }
        }
    }
    if(r&&g&&b){  //R,G,B
        for(int i=1;i<=r;++i){
            for(int j=1;j<=g;++j){
                for(int k=1;k<=b;++k){
                    if(R[i]==G[j]||R[i]==B[k]||G[j]==B[k]||judge(R[i],G[j],B[k])) continue;
                    double a=cal(R[i],G[j]);
                    double b=cal(R[i],B[k]);
                    double c=cal(G[j],B[k]);
                    if(a>(b+c)||b>(a+c)||c>(a+b)) continue;
                    double d=(a+b+c)/2;
                    double temp=sqrt(d*(d-a)*(d-b)*(d-c));
                    ans=max(ans,temp);
                }
            }
        }
    }
    printf("%.5f\n",ans);
    return 0;
}

【题4】

在这里插入图片描述

【解题思路】

本质类似于最长上升子序列,但又不尽相同

举个例子

原序列:3 4 1 2 6 8 9

排序后:1 2 3 4 6 8 9

原下标:3 4 1 2 5 6 7

可以发现原序列中下标为3和4的元素是没有移动的,而其他元素全部都移动了,所以最小的移动次数应该为7-2=5,即元素总个数n减去排序后从前往后有序的个数m

【AC代码】

#include <bits/stdc++.h>
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
using namespace std;
int a[55];
map<int,int> mp;
int main(){
    int n;
    scanf("%d",&n);
    a[0]=0x3f3f3f3f;
    int Min=0;
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        mp[a[i]]=i; //保存序列下标
    }
    sort(a+1,a+n+1);
    int m=1;
    while(m+1<=n&&mp[a[m]]<mp[a[m+1]]) ++m;  //从前往后遍历直到出现无序的情况
    printf("%d\n",n-m);
    return 0;
}

【题5】

在这里插入图片描述

【解题思路】

https://www.nowcoder.com/questionTerminal/621e433919214a9ba46087dd50f09879?f=discussion by 赵翔

dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1)) % 2017;
**dp[i][j]**表示有i个数字及j个小于号所能组成的数量(大于号数量当然是i - j - 1次,后面需要使用)
而加入第i + 1个数字时,分以下四种情况:
1.如果将i+1插入当前序列的开头,即有了1<2,加入后成为3>1<2,会发现等于同时加入了一个大于号!(此时可以无视1与2之间的关系,因为i+1>i)
2.如果将i+1插入当前序列末尾,即1<2变成了 1<2<3,会发现等于同时加入了一个小于号! (此时可以无视1与2之间的关系,因为i+1>i)
3.如果将i+1加入一个小于号之间,即已经有 1<2了,向中间加入3,会发现变成了1<3>2,等于同时加入了一个大于号!
4.如果将i+1加入一个大于号中间,即有了2>1,变成了2<3>1,等于同时加入了一个小于号!
综上所述,**dp[i][j]**等于以上四种情况之和:
dp[i - 1][j] 将i加在开头等于加入一个大于号,即要求i-1个数时已经有了j个小于号
dp[i - 1][j - 1] 将i加在末尾等于加入一个小于号,即要求i-1个数时已经有了j-1个小于号
dp[i - 1][j] * j 将i加在任意一个小于号之间,等于加入了一个大于号;即要求i-1个数时已经有了j个小于号,每个小于号都可以进行这样的一次插入
dp[i - 1][j - 1] * (i- j - 1) 将i加载任意一个大于号之间,等于加入了一个小于号;即要求i-1个数时有了j-1个小于号,而此时共有
(i - 1) - (j - 1)- 1个大于号,每个大于号都要进行一次这样的操作合并同类项即为
dp[i][j] = (dp[i - 1][j - 1] * (i - j) + dp[i - 1][j] * (j + 1))
最后要记得取模

【AC代码】

#include <iostream>
using namespace std;
int dp[1005][1005];
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    dp[1][0]=1;
    for(int i=2;i<=n;++i){
        for(int j=0;j<i;++j){
            if(j==0) dp[i][j]=1;
            else{
                dp[i][j]=((j+1)*dp[i-1][j]+(i-j)*dp[i-1][j-1])%2017;
            }
        }
    }
    printf("%d\n",dp[n][k]);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值