腾讯2019暑期实习生提前批CV岗笔试题


       笔试共有5道编程题,每道题20分,两个小时。以下内容的编写全凭记忆和个人理解,如有什么不对的地方,希望大家见谅。

第一题

题意

       一个直线路上有n个点,你在这条路上的某个位置上,你要到达这n个点中的任意n-1个点,使得经过的路径最短,输出最短路径的路程。

思路

       因为只有一个点不走,最优的路径应该是不走第1个点或者不走第n个点,处理一下特殊情况就行了。但是不知道为啥只过了30%。

代码

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>

using namespace std;

int num[100000+10];

int main()
{
    long long n, a;
    while(scanf("%lld%lld",&n,&a)!=EOF)
    {
        long long ans = 0;
        long long left_num = 0;
        long long right_num = 0;
        for(int i=1;i<=n;++i)
        {
            scanf("%lld",&num[i]);
            if(num[i]<=a)
                left_num++;
        }
        if(left_num == 0)
            ans = num[n-1] - a;
        else if(left_num == n)
            ans = a - num[2];
        else if(left_num == 1)
        {
            long long ans1 = min(a-num[1],num[n-1]-a)+ num[n-1]-num[1];
            long long ans2 = num[n]-a;
            ans = min(ans1, ans2);
        }
        else if(left_num == n-1)
        {
            long long ans1 = a-num[1];
            long long ans2 = min(num[n]-a, a-num[2])+ num[n]-num[2];
            ans = min(ans1, ans2);
        }
        else
        {
            long long ans1 = min(num[n-1]-a, a-num[1]) + num[n-1]-num[1];
            long long ans2 = min(num[n]-a, a-num[2]) + num[n]-num[2];
            ans = min(ans1, ans2);
        }
        printf("%lld\n",ans);

    }
    return 0;
}

第二题

题意

       有一个n层的塔,每层的高度是不同的。小Q要从塔底走到塔顶,走一层耗费的时间和该层高度相同。但是小Q有一个特殊技能,就是小Q会跳,每次跳跃可以选择上升一层或者两层,且不消耗时间,但是弊端是每跳一次后,必须走至少一层才可以再次跳跃。求小Q爬到塔顶耗费的最短时间。

思路

       一个简单的dp。
        ①状态dp[i][0]表示在第i层选择走上去,且到当前第i层为止,花费的最少时间。
        ②状态dp[i][1]表示在第i层选择跳一层,且到当前第i层为止,花费的最少时间。
        ③状态dp[i][2]表示在第i层选择跳两层,且到当前第i层为止,花费的最少时间。
       则状态转移方程可以写为:
        ①dp[i][0]=min(dp[i-2][2], dp[i-1][1], dp[i-1][0])+num[i];
        ②dp[i][1]=dp[i-1][0];
        ③dp[i][2]=dp[i-1][0];
      最后的答案就是min(dp[n+1][0], dp[n+1][1], dp[n+1][2]),这道题过了100%样例。

代码

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>

using namespace std;

int num[10000+10];
int dp[10000+10][4];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d",&num[i]);
        dp[0][0]=dp[0][1]=dp[0][2]=0;
        dp[1][0]=num[1];
        dp[1][1]=0;
        dp[1][2]=0;
        for(int i=2;i<=n+1;++i)
        {
            dp[i][0]=min(min(dp[i-2][2],dp[i-1][1]), dp[i-1][0])+num[i];
            dp[i][1]=dp[i][2]=dp[i-1][0];
            //printf("%d %d %d\n",dp[i][0],dp[i][1],dp[i][2]);
        }
        printf("%d\n",min(min(dp[n+1][0],dp[n+1][1]),dp[n+1][2]));
    }
    return 0;
}

第三题

题意

       有n张纸牌,数字分别是1到n,纸牌按照牌面从小到大排列。现在小Q要把第一张牌抽出,然后把第二张牌放到末尾,再把第三张牌抽出,把第四张牌放到末尾,…,直至没有纸牌。输出抽出的纸牌的顺序。

思路

       用队列模拟,以下代码过了80%,想一想自己也真是挺蠢的,每一次都从队列中pop两个,但是如果队列中剩最后一张纸牌时,就会seg error,改一下应该就是100%了。

代码

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>

using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        queue<int> q;
        for(int i=1;i<=n;++i)
            q.push(i);

        while(!q.empty())
        {
            int tmp = q.front();
            q.pop();
            int tmp2 = q.front();
            q.pop();
            q.push(tmp2);
            printf("%d ",tmp);
        }
        printf("\n");
    }
    return 0;
}

第四题

题意

       有一个 n × m n\times m n×m大小的黑白相间的棋盘,棋盘的左下角是白色块。现在对这个棋盘进行两个操作,①将左下角坐标为 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),右上角坐标为 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)的矩形区域内的全部方块变为白色;②将左下角坐标为 ( x 2 , y 2 ) (x_2,y_2) (x2,y2),右上角坐标为 ( x 3 , y 3 ) (x_3,y_3) (x3,y3)的矩形区域内的全部方块变为黑色。输出经过这两次操作以后棋盘上的黑白块个数。

思路

       模拟两次操作,再对两个矩形的重叠部分特殊处理一下就可以了。以下为通过样例100%的代码。

代码

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>

using namespace std;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long n,m;
        scanf("%lld%lld",&n,&m);
        long long x0,y0,x1,y1;
        long long x2,y2,x3,y3;
        scanf("%lld%lld%lld%lld",&x0,&y0,&x1,&y1);
        scanf("%lld%lld%lld%lld",&x2,&y2,&x3,&y3);
        long long sum_num = n*m;
        long long white_num = 0;
        long long black_num = 0;
        if(sum_num%2 == 1)
        {
            black_num = sum_num/2;
            white_num = black_num + 1;
        }
        else
        {
            black_num = sum_num/2;
            white_num = black_num;
        }
        //printf("----%lld %lld\n",white_num, black_num);
        long long deta_x1 = x1 - x0 + 1;
        long long deta_y1 = y1 - y0 + 1;
        if((deta_x1*deta_y1)%2 == 1)
        {
            if((x0+y0)%2 ==0) //white
            {
                white_num = white_num + ((deta_x1*deta_y1)/2) ;
                black_num = sum_num - white_num ;
            }
            else // black
            {
                white_num = white_num + ((deta_x1*deta_y1)/2) + 1;
                black_num = sum_num - white_num ;
            }
        }
        else
        {
            white_num = white_num + ((deta_x1*deta_y1)/2);
            black_num = sum_num - white_num ;
        }

        long long deta_x2 = x3 - x2 + 1;
        long long deta_y2 = y3 - y2 + 1;
        if((deta_x2*deta_y2)%2 == 1)
        {
            if((x2+y2)%2 ==0) //white
            {
                black_num = black_num + ((deta_x2*deta_y2)/2) + 1;
                white_num = sum_num - black_num ;
            }
            else // black
            {
                black_num = black_num + ((deta_x2*deta_y2)/2);
                white_num = sum_num - black_num ;
            }
        }
        else
        {
            black_num = black_num + ((deta_x2*deta_y2)/2) ;
            white_num = sum_num - black_num ;
        }
        //printf("----%lld %lld\n",white_num, black_num);
        long long x4 = max(x0,x2);
        long long y4 = max(y0,y2);
        long long x5 = min(x1,x3);
        long long y5 = min(y1,y3);
        //printf("--------- %lld %lld %lld %lld  \n", x4,y4,x5,y5);
        if(x5>=x4 && y5>=y4)
        {
            long long deta_x3 = x5 - x4 + 1;
            long long deta_y3 = y5 - y4 + 1;
            long long tmp = deta_x3 * deta_y3;
            if( tmp % 2 == 1)
            {
                if((x4+y4)%2 ==0) //white
                {
                    black_num = black_num + ((deta_x3*deta_y3)/2);
                    white_num = sum_num - black_num ;
                }
                else // black
                {
                    black_num = black_num + ((deta_x3*deta_y3)/2) +1 ;
                    white_num = sum_num - black_num ;
                }
            }
            else
            {
                black_num = black_num + ((deta_x3*deta_y3)/2);
                white_num = sum_num - black_num ;
            }
        }
        printf("%lld %lld\n",white_num, black_num);
    }
    return 0;
}

第五题

题意

       一个大小为n的数组,对于数组中的第 i ( 2 ≤ i ≤ n ) i(2\leq i\leq n) i(2in)个数字 A i A_i Ai,输出 a n s i = m i n j ∣ A j − A i ∣ ans_i=min_j|A_j-A_i| ansi=minjAjAi,并输出对应的位置 j j j,如果有多个相同的 a n s i ans_i ansi,输出最小的 j j j

思路

       写到这道题只剩8分钟了,虽然知道暴力对于 1 0 5 10^5 105的数据肯定过不了,但还是草草的写了个暴力,过了50%。

代码

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<string>

using namespace std;

int num[100000+10];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&num[i]);
        }
        for(int i=2;i<=n;++i)
        {
            int ans = 999999999;
            int ttt = i-1;
            for(int j=i-1;j>=1;--j)
            {
                int tmp = fabs(num[j]-num[i]);
                if(tmp <= ans)
                {
                    ttt = j;
                    ans = tmp;
                }
            }
            printf("%d %d\n",ans,ttt);
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值