网易雷火8.6 游戏研发工程师 笔试

说明

总共3个小时,题目描述纯属个人回忆,可能用词和原版有所区别。前3道a了,第四道中的4种情况只推导出了2种,过了56%,请参考其他大佬。

1. 队伍匹配

题目描述

有两个人想组队参加匹配2v2游戏,他们的分数分别是q1和q2,组队匹配的规则是两支队伍的各自分数和之间的差距小于等于p;如果参加者是两人,则自动组成队,如果是单人玩家,则可以与另外一名单独玩家临时组队。

输入

第一行输入q1,q2,p,x,其中q1/q2/p的定义如上文所示,x为其他双人组的数目。

接下来x行,每行两个数,分别是这双人组的分数

接着输入y,y为单人组的数目。

解析来y行,每行一个数,是单人玩家的分数。

输出

这两个人能匹配的到的对手的排列组合数。

解析

送分题,计算双人组符合条件的数目a,再O(n2)暴力遍历单人组符合条件的数目,相加就完了。

import java.util.Scanner;

public class Main1 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int q1 = scanner.nextInt();
        int q2 = scanner.nextInt();
        int p = scanner.nextInt();
        int x = scanner.nextInt();
        int[] a = new int[x];
        int[] b = new int[x];

        int res = 0;
        int q = q1+q2;
        for(int i=0;i<x;i++){
            a[i] = scanner.nextInt();
            b[i] = scanner.nextInt();
            if(Math.abs(a[i]+b[i]-q)<=p)
                res++;
        }

        int y = scanner.nextInt();
        int[] c = new int[y];

        for(int i=0;i<y;i++)
            c[i] = scanner.nextInt();
        for(int i=0;i<y;i++)
            for(int j=i+1;j<y;j++){
                if(Math.abs(c[i]+c[j]-q)<=p)
                    res++;
            }

        System.out.println(res);

    }
}

2. 跑酷

题目描述

一名玩家参加跑酷游戏,赛道均分为一段段高低不等的台阶,玩家从相同高度的台阶前进需要t1,跳到比现有台阶高一级的台阶需要t2,跳到比现有台阶低的台阶需要t3。同时游戏存在另一条平行赛道,平行赛道每个台阶的高度与原对应台阶的高度的和恒为4。玩家也可以切换在对应位置的两条赛道来回切,花费t4。玩家从起点跑到最后一个台阶视为游戏完成。

输入

第一行 n t1 t2 t3 t4
第二行有n个数,分别是第一条赛道的各台阶高度

输出

玩家完成游戏的最短耗时

解析

DFS,在每个位置上要么继续跑,要么切跑道,按两条跑法搜索,若当前时长已经大于最小时长则剪枝。另外用一个hashmap保存已经计算过的结果,由于有两条赛道,所以最多保存2n的位置上到终点的最短时间。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main2 {
    static long minTime;
    static int n;
    static int[] h;
    static int[] h2;
    static int t1,t2,t3,t4;
    static Map<String,Long> map;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        t1 = scanner.nextInt();
        t2 = scanner.nextInt();
        t3 = scanner.nextInt();
        t4 = scanner.nextInt();

        h = new int[n];
        h2 = new int[n];
        minTime = Long.MAX_VALUE;
        map = new HashMap<>();

        for(int i=0;i<n;i++){
            h[i] = scanner.nextInt();
            h2[i] = 4 - h[i];
        }
        fun(0,0,true);
        System.out.println(minTime);

    }

    static void fun(int now,long t,boolean flag){
        if(t>=minTime)
            return;
        if(map.containsKey(now+""+flag)){
            long oldT = map.get(now+""+flag);
            if(t>=oldT)
                return;
        }
        map.put(now+""+flag,t);

        if(flag){
            if(now!=n-1){
                if(h[now+1]==h[now])
                    fun(now+1,t+t1, true);
                else if(h[now+1]<h[now])
                    fun(now+1,t+t3, true);
                else if(h[now+1]-h[now]==1)
                    fun(now+1,t+t2, true);
            }else
                minTime = Math.min(minTime,t);
        }else{
            if(now!=n-1){
                if(h2[now+1]==h2[now])
                    fun(now+1,t+t1, false);
                else if(h2[now+1]<h2[now])
                    fun(now+1,t+t3, false);
                else if(h2[now+1]-h2[now]==1)
                    fun(now+1,t+t2, false);
            }else
                minTime = Math.min(minTime,t);
        }
        fun(now,t+t4,!flag);
    }
}

3. 解析配置文件

题目描述

有一个配置文件,对它进行逐行解析,满足以下条件:

  • 需要存在空行,空行指的是仅有空格的行。
  • 若该行以“#”开头,则表示该行为注释行,忽略改行
  • 每一行只有一个key和value,形式如 key=value,若出现多个等号,则以第一个等号为主,其他等号视为value的值。
  • 无论是key和value都要略去前后的空格
  • value种可能存在{key}的情况,称为引用value,需要奖{key}替换为key对应的value。若引用的值不存在或循环引用,则解析失败。
  • 引用的大括号不匹配也视为匹配失败
  • 题目保证key和value自身没有大括号字段,即大括号一定是引用。

输入

第一行一个t,表示有t行数据。
接下来t行,即为文件的内容
最后一行key,表示要查询的key

输出

如果解析失败,输出“ERROR”;
如果解析成功,但不存在该key,输出“NULL”
如果解析成功并存在该key,输出该key的value

解析

按照题目要求逐行解析即可,先把全文空格删了,遇到空行或者注释行直接跳过。
用map表示已经解析出来的键值对,map2表示含有引用等待继续解析的键值对。
逐行解析,如果遇到引用,则加入map2,如果没有引用且格式正确,插入map。
接下来进行循环:
对于map2中的任意value,可以通过大括号得知求出该value中的引用有哪些,如果这些引用在map中存在,则替换它。
若替换后该value不存在引用,则将其从map2移到map1
当该轮循环没有发生替换,则退出循环。
退出循环后,检查map2,如果map2的大小不为0,则表示存在循环引用或引用不存在,直接输出解析失败。
如果map2的大小为0,说明全部解析成功,按题目要求返回map中的value即可。

import java.util.*;

public class Main3 {

    static void fun3(){
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        Map<String,String> map = new HashMap<>();
        Map<String,String> map2 = new HashMap<>();
        scanner.nextLine();
        while(t>0){
            String line = scanner.nextLine();
            if(line.replace(" ","").equals("")||line.startsWith("#")){
                t--;
                continue;
            }
            int index = line.indexOf("=");
            String key = line.substring(0,index).trim();
            String value = line.substring(index+1).trim();

            if(key.equals("")||value.equals("")){
                System.out.println("ERROR");
                return;
            }
            if(value.contains("{")&&!check(value)){
                System.out.println("ERROR");
                return;
            }
            if(value.contains("{"))
                map2.put(key,value);
            else
                map.put(key,value);
            t--;
        }
        boolean flag = true;
        while(flag){
            flag = false;
            if(map2.keySet().size()==0)
                continue;
            List<String> temp = new ArrayList<>();
            for(String key:map2.keySet()){
                String value = map2.get(key);
                List<String> childs = getChild(value);
                for(String child:childs){
                    if(map.containsKey(child)){
                        value = value.replace("{"+child+"}",map.get(child));
                        flag = true;
                    }
                }
                if(value.contains("{"))
                    map2.put(key,value);
                else{
                    temp.add(key);
                    map.put(key,value);
                }
            }
            for(String key:temp)
                map2.remove(key);
        }

        String url = scanner.nextLine();
        if(map2.keySet().size()==0)
            System.out.println(map.getOrDefault(url, "NULL"));
        else
            System.out.println("ERROR");
    }

    static boolean check(String s){
        int cnt = 0;
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='{')
                cnt++;
            else if(s.charAt(i)=='}')
                cnt--;
            if(cnt<0)
                return false;
        }
        return cnt == 0;
    }

    static List<String> getChild(String s){
        List<String> res = new ArrayList<>();
        StringBuilder temp = new StringBuilder();
        boolean flag = false;
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='{')
                flag = true;
            else if(s.charAt(i)=='}'){
                flag = false;
                res.add(temp.toString());
                temp = new StringBuilder();
            }
            else{
                if(flag)
                    temp.append(s.charAt(i));
            }
        }
        return res;
    }
    public static void main(String[] args) {
        fun3();
    }
}

4. 莫比乌斯赛车大逃杀

题目描述

赛车的跑道是一个长为M的纸条,但是将纸条一头旋转180后,接入另一头,形成一个莫比乌斯环。该环上有N量赛车,你控制1号赛车可以做以下行为:

  • 攻击你前方或后方距离小于等于L的赛车,使其退赛
  • 立刻瞬移到纸带背面,速度和方向不变
    求要歼灭除你自己之外的其他赛车,最短要多久,结果保留两位小数。

    输入:

    第一行 m n L
    第二行 有n个数,分别是1N号赛车的初始位置
    第三行 有n个数,分别是1
    N号赛车的速度,方向一致向前

    输出:

    使得只有自己留在场上的最短时间

    解析

    莫比乌斯环,由于自己可以瞬移到纸带的正反面,以自己为参考系,速度与方向不变,相当于其他车在抵达终点后,瞬移到起点又开始跑。(实际上其他车是跑到纸带的背面的新一圈,但对你而言没有区别),假设i号车的速度为vi,初始位置为si,只用考虑vi与v1,si与s1之间的大小关系所形成的四种情况追逐关系就能算出1号车歼灭i号车所需要的时间。最后输出最大的那个时间。
    由于时间来不及了,我只推导出两种,过了56%的用例...
import java.util.Scanner;

public class Main4 {

    static int m;
    static int l;
    static int s0;
    static int v0;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        m = scanner.nextInt();
        int n = scanner.nextInt();
        l = scanner.nextInt();
        int[] s = new int[n];
        int[] v = new int[n];

        for(int i=0;i<n;i++)
            s[i] = scanner.nextInt();
        for(int i=0;i<n;i++)
            v[i] = scanner.nextInt();
        s0 = s[0];
        v0 = v[0];
        double max = 0;
        for(int i=1;i<n;i++)
            max = Math.max(max,fun(s[i],v[i]));
        System.out.printf("%.2f\n",max);
    }

    public static double fun(int s1,int v1){
        if(Math.abs(s1-s0)<=l)
            return 0;
        if(s1>s0&&v1>=v0)
            return (m-s1+s0-l)/(double)(v1-v0);
        if(s1>s0&&v1<v0){


            double t = (m-s1)/(double)v1;
            double t2 = (s1-s0-l)/(double)(v0-v1);
            if(t2<=t)
                return t2;
            else{

                //return 0;
            }


        }
        if(s1<s0&&v1>=v0){
            double t = (m-s0)/(double)v0;
            double t2 = (s0-s1-l)/(double)(v1-v0);
            if(t2<=t)
                return t2;
            else{
                t = (m-s1)/(double)v1;
                double s3 = s0+ t*v0-m;
                return t+s3/(double)(v1-v0);
            }
        }

        if(s1<s0&&v1<v0){
            //return 0;
            return (s1-s0+m-l)/(double)(v0-v1);
        }
        return 0;
    }
}
#网易雷火##笔经#
全部评论
第四道题的话不需要考虑的太复杂,代码忘记了,大概说下思路吧。 从题干中提取几个关键信息:1.赛道是个环;2.技能无cd;3.闪现距离是半个环;4.杀敌技能可以看作死亡范围。 下面是思路:1.计算其他车起始位置与自己车起始位置的相对位置(后面将自己车的位置视作起点);2.将自身视作静止,计算其他人相对于自己的运动速度(后面都是用这个速度计算);3.因为自己已经静止,所以在整个环上就只有两个死亡范围,分别是起点区间和起点对面的区间,而且起点对面区间的中心点和起点的距离是知道的;4.在知道上面这些之后,又因为已经计算了其它车的相对速度,那么只需要知道,这些车到死亡区间的最短时间是多长即可。如下图例: 如果敌人B逆时针转,那么需要走的最短距离就是从当前位置到区间1右端点的距离,速度是之前计算的相对速度,相除就得到时间;如果顺时针转,就是到区间2的右端点。 计算所有车的死亡时间之后取最大值即可(因为技能0cd,可以随意反复横跳或者释放击杀技能) 思路好像和楼主很像,但是a了100%,不知道是不是因为语言的问题😅(我用的c++)
1 回复 分享
发布于 2021-08-10 15:04

相关推荐

尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
#我和xx公司的爱恨情仇#&nbsp;怎么会有这么**的公司!实习ld跟我说,在这实习秋招会有很大优势,没太大问题;线下一面二面水的很,手撕都是easy,二面面试官甚至说,你随便手撕个题目就行,找个代码量多的题目,然后我写了一个bfs图算法。主管面也是基本上纯聊天,然后甚至问我预期薪资,我说虽然我有互联网公司offer但是更想来华子,认可企业文化。面试完后,保温电话说根据面评开14a没问题,过了一段时间后去问了对接人,先说11月底开,后来说12月底开,昨天去问,他说你不是签了美团了吗,我们已经发完全部offer了。tmd那你不早说,我还在这等。我问了我们这个部门的其他实习生(三级部门下8个实习生,我们四级部门下就有5个,按理说我们部门应该缺人吧),结果其他实习生全军覆没,之前都收到降温电话要签个其他offer保底,实习生中甚至有人空白三方在allin华子,最逆天的是,其中一个是优秀实习生,他也没开出来。问那个优秀实习生,他说他在这实习时接口人天天给他洗脑说,在这实习只有不想来的,没有泡不出来的(如图1)。我接口人也是这么跟我说的,说我们2012实验室下面都偏预研,部门加班少,我们部门确实还行,而且本身华为比互联网稳定,后期还有股票,退休保留股票一直分红(补充:只有5%的人可以熬到40岁以上退休分股),你看看华为那么多od,人家为什么社招想来华为当od呢,因为华为真的稳定啊(后来想想他们来当od应该是没有更好的选择了吧,xhs上那个清华姚班都来华为当od)。我跟几个实习生已经转投其他部门了,那个优秀实习生去找别的部门hr时,人家问:你优秀实习生也要换部门吗,没遇到你这种情况之前为了选华为还是美团我还纠结了1个多月,现在想想真**,这**公司谁来谁知道,华子稳定个**,这里补充一下,35岁下岗就是华子最早提出来的。还有华为内部转岗的事,后来问了下很多大公司都可以内转,华子内转还要背绩效,去新部门会有很大绩效压力,原部门绩效太差还不能转,****。这**泡池子机制也是遥遥领先,其他互联网公司纷纷效仿。还有那5%公积金真恶心。之前认识一个腾讯提前批哥们,他杭电本科生,hr打电话还恶心他,给他开13a,总包比腾讯少20w,跟他说一大堆什么企业稳定,前景好,技术遥遥领先(图2)另外,还有个签约阿里被华为恶心的(图3)我和腾讯提前批的哥们的故事是真的,可以保证确有其事,图3是道听途说,不保证真实性,但我觉得这**公司真有可能发生这种诈骗故事
好吃的麦乐鸡块:这公司真的恶心,毫无信誉可言
点赞 评论 收藏
分享
评论
6
30
分享
牛客网
牛客企业服务