华为2019暑期实习笔试题


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

第一题

题意

       给出一个字符串,由许多子串组成,每个子串长度都是9,如果子串的第一位是0,就将该子串反序输出,如果子串的第一位是1,就将该子串正序输出。

思路

       没啥说的,签到题,暴力就ok,可是我代码写的太丑了。。。

代码

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

using namespace std;

char s[500];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        scanf("%s",s);
        int len = strlen(s);
        s[len]='1';
        len++;
        int start = 1;
        int end = 1;
        int rev = 0;
        int flag = 0;
        int str_num = 0;
        for(int i=0;i<len;)
        {
            if(s[i] == '0')
            {
                if(flag == 0)
                {
                    rev = 1;
                    flag = 1;
                    start = i+1;
                    i=i+9;
                }
                else
                {
                    flag = 0;
                    end = i-1;
                    if(str_num == 0)
                        str_num = 1;
                    else
                        printf(" ");
                    if(rev == 1)
                    {
                        for(int j = end; j>=start; --j)
                            printf("%c",s[j]);
                    }
                    else
                    {
                        for(int j = start; j<=end; ++j)
                            printf("%c",s[j]);
                    }
                }
            }
            else if(s[i] == '1')
            {
                if(flag == 0)
                {
                    rev = 0;
                    flag = 1;
                    start = i+1;
                    i=i+9;
                }
                else
                {
                    flag = 0;
                    end = i-1;
                    if(str_num == 0)
                        str_num = 1;
                    else
                        printf(" ");
                    if(rev == 1)
                    {
                        for(int j = end; j>=start; --j)
                            printf("%c",s[j]);
                    }
                    else
                    {
                        for(int j = start; j<=end; ++j)
                            printf("%c",s[j]);
                    }
                }
            }
            else
                ++i;
        }
        printf("\n");
    }
    return 0;
}

第二题

题意

       一个蜜蜂,最开始在原点,要去五个其他位置采蜜,求采完回到原点的最短路径。

思路

       我写了一个特别丑的暴力,真的不能再丑了。觉得写一个全排列或者搜索能好看一点。需要注意的是最后输出的时候,要把答案减0.5,因为.0lf会四舍五入,而题中要求截断小数部分。

代码

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

using namespace std;

double x[10],y[10];
double edge[10][10];

double calc_dis(double x1,double y1,double x2,double y2)
{
    double tmp1 = (x1-x2)*(x1-x2);
    double tmp2 = (y1-y2)*(y1-y2);
    return sqrt(tmp1+tmp2);
}

int main()
{
    while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&x[1],&y[1],&x[2],&y[2],&x[3],&y[3],&x[4],&y[4],&x[5],&y[5])!=EOF)
    {
        x[0]=y[0]=0;
        for(int i=0;i<=5;++i)
            for(int j=0;j<=5;++j)
                edge[i][j]=edge[j][i]=calc_dis(x[i],y[i],x[j],y[j]);

        double ans = 99999999999;
        for(int i=1; i<=5; ++i)
            for(int j=1; j<=5; ++j)
                for(int k=1; k<=5; ++k)
                    for(int l=1; l<=5; ++l)
                        for(int p=1; p<=5; ++p)
                        {
                            if(i==j || i==k || i==l || i==p ||
                               j==k || j==l || j==p ||
                               k==l || k==p ||
                               l==p)
                               continue;
                            double tmp = edge[0][i] + edge[i][j] + edge[j][k] + edge[k][l] + edge[l][p] +edge[0][p];
                            ans = min(ans, tmp);
                        }
        printf("%.0lf\n",ans-0.5);
    }
    return 0;
}

第三题

题意

       有个网格,在某些格子上有水果,我们可以横、竖、对角(2种)切水果,问最少几刀可以把水果切没。

思路

       我觉得是搜索,然后写啊写,到最后结束了知道’\\\'是续行符,我有一行代码由于自己写了注释,咋都运行不了,我都蒙了。我的搜索太丑了,可以再优雅点,有些地方也能记忆化一下,我也不知道会不会TLE,会不会WA,1个半小时都在调试。。。

代码

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

using namespace std;

int x[60],y[60];
int vis[60];

int vis_num;
int max_n=40;
int max_m=50;
int n;
int end_ans;

int calc_cut(int start, int style)
{
    printf("start:%d %d style=%d\n",x[start],y[start],style);
    int ans=0;
    if(style == 1)
    {
        for(int i=1;i<=n;++i)
            if(x[i]==x[start] && vis[i]==0)
                ans++;
    }
    if(style == 2)
    {
        for(int i=1;i<=n;++i)
            if(y[i]==y[start] && vis[i]==0)
                ans++;
    }
    if(style == 3)
    {
        for(int i=1;i<=n;++i)
        {
            if((x[i]-x[start])==(y[i]-y[start]) && vis[i]==0)
            {
                ans++;
                //printf("i=%d %d %d\n",i,x[i],y[i]);
            }
        }
    }
    if(style == 4)
    {
        //cout<<"---------"<<endl;
        for(int i=1;i<=n;++i)
            if((x[i]-x[start])==(y[start]-y[i]) && vis[i]==0)
            {
                ans++;
                //printf("i=%d %d %d\n",i,x[i],y[i]);
            }
    }
    return ans;
}

int cut[10];
void dfs(int start, int vis_num, int cut_times)
{
    if(vis_num >= n)
        return ;

    printf("----------------------------\n");
    cut[1] = calc_cut(start,1);// ---
    cut[2] = calc_cut(start,2);// |||
    cut[3] = calc_cut(start,3);// \\\
    cut[4] = calc_cut(start,4);// 

    int max_cut=cut[1];
    int max_i=1;
    for(int i=1;i<=4;++i)
        if(cut[i]>max_cut)
        {
            max_cut=cut[i];
            max_i=i;
        }
    //printf("start=%d max_cut=%d cut_i=%d cut_times=%d vis_num=%d\n",start,max_cut,max_i,cut_times,vis_num);
    //printf("%d %d %d %d\n\n\n",cut[1],cut[2],cut[3],cut[4]);
    //printf("%d\n",max_i);
    if(max_i == 1)
    {
        int next;
        for(int i=1;i<=n;++i)
            if(x[i]==x[start] && vis[i]==0)
            {
                vis[i]=1;
                vis_num++;
            }
            else
                next=i;

        if(vis_num == n)
            end_ans = min(end_ans, cut_times);
        else
            dfs(next, vis_num, cut_times+1);
    }
    if(max_i == 2)
    {
        int next;
        for(int i=1;i<=n;++i)
            if(y[i]==y[start] && vis[i]==0)
            {
                vis[i]=1;
                vis_num++;
            }
            else
                next=i;

        if(vis_num == n)
            end_ans = min(end_ans, cut_times);
        else
            dfs(next, vis_num, cut_times+1);
    }
    if(max_i == 3)
    {
        int next;
        for(int i=1;i<=n;++i)
            if((x[i]-x[start])==(y[i]-y[start]) && vis[i]==0)
            {
                vis[i]=1;
                vis_num++;
            }
            else
                next=i;

        if(vis_num == n)
            end_ans = min(end_ans, cut_times);
        else
            dfs(next, vis_num, cut_times+1);
    }
    if(max_i == 4)
    {
        //printf("--------------------\n");
        int next;
        for(int i=1;i<=n;++i)
            if((x[i]-x[start])==(y[start]-y[i]) && vis[i]==0)
            {
                vis[i]=1;
                vis_num++;
            }
            else
                next=i;

        if(vis_num == n)
            end_ans = min(end_ans, cut_times);
        else
            dfs(next, vis_num, cut_times+1);
    }
    return ;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d%d",&x[i],&y[i]);

        memset(vis,0,sizeof(vis));
        end_ans=1234567890;
        dfs(1, 0, 1);

        printf("%d\n", end_ans);
    }
    return 0;
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值