百度2016研发工程师在线编程题

题目链接:http://www.nowcoder.com/test/question/analytic?tid=1667855


[编程题]罪犯转移
C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有一个罪行值,值越大罪越重。现在为了方便管理,市长决定转移入狱时间连续的c名犯人,同时要求转移犯人的罪行值之和不超过t,问有多少种选择的方式? 

输入描述:
第一行数据三个整数:n,t,c(1≤n≤2e5,0≤t≤1e9,1≤c≤n),第二行按入狱时间给出每个犯人的罪行值ai(0≤ai≤1e9)


输出描述:
一行输出答案。

输入例子:
3 100 2
1 2 3

输出例子:
2
题意:求区间长度为c的连续序列的和小于等于t的区间的个数!

思路:我用两个变量来控制区间的大小,先向前扩展到c的长度,然后左区间向右移动,寻找下一个符合条件的区间;sum用来记录区间和,O(n)

#include<stdio.h>
int num[200005];
int main()
{
    int n,t,c;
    while(scanf("%d%d%d",&n,&t,&c)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);
        }
        if(c==0){printf("0\n");continue;}
        int cnt=0;
        int sum=0;
        int i=0,j=0;
        for(;i<n&&j<n;j++)
        {
            if(num[j]>t) {sum=0;i=j+1;}
            if(j-i+1<c) {sum+=num[j];continue;}
            if(j-i+1>c) {sum-=num[i++];}
            if(j-i+1==c)
            {
                sum+=num[j];
                if(sum<=t)
                    cnt++;
                else if(sum>t)
                {
                    while(sum>t)
                    {
                        sum-=num[i++];
                    }
                }
            }

        }
        printf("%d\n",cnt);
    }
    return 0;
}


[编程题]裁减网格纸
度度熊有一张网格纸,但是纸上有一些点过的点,每个点都在网格点上,若把网格看成一个坐标轴平行于网格线的坐标系的话,每个点可以用一对整数x,y来表示。度度熊必须沿着网格线画一个正方形,使所有点在正方形的内部或者边界。然后把这个正方形剪下来。问剪掉正方形的最小面积是多少。 
输入描述:
第一行一个数n(2≤n≤1000)表示点数,接下来每行一对整数xi,yi(-1e9<=xi,yi<=1e9)表示网格上的点


输出描述:
一行输出最小面积

输入例子:
2
0 0
0 3

输出例子:
9
题意:求包围点的最小正方形面积,且正方形必须沿着网格剪,so。。。本来以为是凸包的,但认真看清题意,原来只是个水题,贪心就可以了。找到最大和最小的x,y,求最大的边长,即可求最小的面积。

//由于必须要沿着网格线剪下,即必须到x、y轴
//so 只有要找最大最小的x,y即可
#include<stdio.h>
#include<algorithm>
using namespace std;
struct point
{
    int x;
    int y;
}po[1005];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&po[i].x,&po[i].y);
        }
        int maxx=po[0].x;
        int minx=po[0].x;
        int maxy=po[0].y;
        int miny=po[0].y;
        for(int i=1;i<n;i++)
        {
            maxx=max(maxx,po[i].x);
            minx=min(minx,po[i].x);
            maxy=max(maxy,po[i].y);
            miny=min(miny,po[i].y);
        }
        int div=max(maxx-minx,maxy-miny);
        printf("%d\n",div*div);
    }
    return 0;
}


[编程题]钓鱼比赛
ss请cc来家里钓鱼,鱼塘可划分为n*m的格子,每个格子每分钟有不同的概率钓上鱼,cc一直在坐标(x,y)的格子钓鱼,而ss每分钟随机钓一个格子。问t分钟后他们谁至少钓到一条鱼的概率大?为多少?

输入描述:
第一行五个整数n,m,x,y,t(1≤n,m,t≤1000,1≤x≤n,1≤y≤m);
接下来为一个n*m的矩阵,每行m个一位小数,共n行,第i行第j个数代表坐标为(i,j)的格子钓到鱼的概率为p(0≤p≤1)


输出描述:
输出两行。第一行为概率大的人的名字(cc/ss/equal),第二行为这个概率(保留2位小数)

输入例子:
2 2 1 1 1
0.2 0.1
0.1 0.4

输出例子:
equal
0.20
题意:略

思路:简单的概率题,首先求<<至少钓到一条鱼的概率=1-一条都钓不到的概率;>>那么现在来求各自钓不到的鱼的概率,cc一直不动,所以很简单,那么ss每次都是随机选择,所以我们要求他的数学期望,在一次选择中不能钓到鱼的概率为1-(每个格子钓到鱼的概率的和 / 总格子数) ;由于是要比较t次,在概率中表示为pow(),最后1-不能的=能的;


#include<stdio.h>
#include<math.h>

int main()
{
    int n,m,x,y,t;
    while(scanf("%d%d%d%d%d",&n,&m,&x,&y,&t)!=EOF)
    {
        double cc=0.0,ss=0.0;
        double tmp;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                scanf("%lf",&tmp);
                if(i==x&&j==y) cc=1-tmp;
                ss+=tmp;
            }
        }
        ss=1-ss/(n*m);
        cc=1-pow(cc,t);
        ss=1-pow(ss,t);
 //               printf("%f\t%f\n",ss,cc);
        if(cc==ss)
        {
            printf("equal\n%.2f\n",cc);
        }
        else if(ss>cc)
        {
            printf("ss\n%.2f\n",ss);
        }
        else
        {
             printf("cc\n%.2f\n",cc);
        }

    }
    return 0;
}


[编程题]蘑菇阵
现在有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?

输入描述:
第一行N,M,K(2 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。


输出描述:
输出一行,代表所求概率(保留到2位小数)

输入例子:
2 2 1
2 1

输出例子:
0.50
思路:由于每个格子除边界只能向两个方向出度,那么对于每个格子除边界也有两个地方的入度;我们把问题分解,对于当前位置的方法数是他入度方法数的*0.5的和,这里特别注意边界,由于他只有一个方向出度,所以概率不是乘以0.5而是乘以1;(对了,有蘑菇的地方标记下,p=0)

想清楚了,就很简单了。

#include<stdio.h>
#include<string.h>
int main()
{
    double p[25][25],vis[25][25];
    int n,m,k;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        memset(p,0,sizeof(p));
        memset(vis,0,sizeof(vis));
        int x,y;
        for(int i=0;i<k;i++)
        {
            scanf("%d%d",&x,&y);
            vis[x][y]=1;
        }
        p[1][1]=1;
        if(vis[1][1]||vis[n][m]) {printf("0.00\n");continue;}
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(i==1&&j==1) continue;
                if(vis[i][j]) p[i][j]=0;
                else
                {
                    if(j==m) p[i][j]+=p[i-1][j]*0.5;
                    if(i==n) p[i][j]+=p[i][j-1]*0.5;
                    p[i][j]+=p[i-1][j]*0.5+p[i][j-1]*0.5;
                }
            }
        }
        printf("%.2f\n",p[n][m]);

    }
    return 0;
}

这次的编程题都不是很难,我在练习的时候没有把握好时间,最后一题来不及写了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值