网易笔试20220317题解

第一题 锯齿数独
判读该数独能否填完。
如果有多种填法就输出Multiple;
如果有一种就输出Unique并输出该种填法;
如果不能填完就输出No。

暴力回溯,注意每一行每一列也要满足数独要求。

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int x, y;
};

// int ans;
vector<string> ans_grid;
set<vector<string>>ans;//记录所有解法,set用来去重

bool check(vector<string> &grid, vector<vector<Node>> &pos) {
    
    //判断每个锯齿是否满足数独要求
    for(int i = 0; i < 3; i++) {
        vector<int>count(3);
        for(int j = 0; j < 3; j++) {
            if(isdigit(grid[pos[i][j].x][pos[i][j].y])) count[grid[pos[i][j].x][pos[i][j].y] - '1']++;
        }
        if(count[0] != 1 || count[1] != 1 || count[2] != 1) return false;
    }

    //判断每行是否满足数独要求
    for(int i = 0; i < 3; i++) {
        vector<int>count(3);
        for(int j = 0; j < 3; j++) {
            if(isdigit(grid[i][j])) count[grid[i][j] - '1']++;
        }
        if(count[0] != 1 || count[1] != 1 || count[2] != 1) return false;
    }

    //判断每列是否满足数独要求
    for(int i = 0; i < 3; i++) {
        vector<int>count(3);
        for(int j = 0; j < 3; j++) {
            if(isdigit(grid[j][i])) count[grid[j][i] - '1']++;
        }
        if(count[0] != 1 || count[1] != 1 || count[2] != 1) return false;
    }


    // for(auto &i: grid) cout << i << endl;
    //     cout << endl;
    return true;
}

void dfs(vector<string> &grid, vector<vector<Node>> &pos) {
    int x = -1, y = -1;
    //寻找下一个*,找不到x就等于-1
    for(int i = 0; i < 3; i++) {
        for(int j = 0; j < 3; j++) {
            if(grid[i][j] == '*') {
                x = i, y = j;
                break;
            }
        }
        if(x != -1) break;
    }
    // cout << x << " " << y << endl;
    // cout << endl;
    if(x != -1) {//还有*没填
        grid[x][y] = '1';
        dfs(grid, pos);
        grid[x][y] = '2';
        dfs(grid, pos);
        grid[x][y] = '3';
        dfs(grid, pos);
        grid[x][y] = '*';
    } else {
        if(check(grid, pos)) {//填完了就检查是否满足要求
            ans.insert(grid);
            ans_grid = grid;
        }
    }
}

int main() {

    int T;
    cin >> T;
    while(T--) {
        vector<string>grid(3);
        for(int i = 0; i < 3; i++) cin >> grid[i];
        vector<vector<Node>>pos(3, vector<Node>(3));//记录三个锯齿
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                cin >> pos[i][j].x >> pos[i][j].y;
            }
        }
        // ans = 0;
        ans.clear();
        dfs(grid, pos, 0, 0);
        if(ans.size() == 1) {
            cout << "Unique" << endl;
            for(int i = 0; i < 3; i++) cout << ans_grid[i] << endl;
        } else if(ans.size() == 0) {
            cout << "No" << endl;
        } else {
            cout << "Multiple" << endl;
        }
    }


    return 0;
}


第二题 黑白棋

黑白轮流下,每次判断八个方位中最远的异色棋位置,然后把中间的棋子颜色反转,并且一个棋子不能被连续两轮反转颜色

直接模拟,注意只考虑连续的棋子,即中间不能有空位!!

#include <bits/stdc++.h>
using namespace std;

int dir[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};


int main() {

    int T;
    cin >> T;
    while(T--) {
        int n, m;
        cin >> n >> m;
        vector<string>s(n);
        for(int i = 0; i < n; i++) cin >> s[i];
        vector<vector<bool>>last(n, vector<bool>(n, false));//记录上一轮哪些棋子动过
        char now = 'w';
        for(int i = 0; i < m; i++) {
            int x, y;
            cin >> x >> y;
            // cout << endl;
            vector<vector<bool>>current(n, vector<bool>(n, false));//记录当前哪些棋子动过
            s[x][y] = now;
            // current[x][y] = true;
            for(int k = 0; k < 8; k++) {
                int far_x = -1, far_y = -1;
                int cur_x = x + dir[k][0], cur_y = y + dir[k][1];
                while(cur_x >= 0 && cur_x < n && cur_y >= 0 && cur_y < n) {//找到最远的异色棋子位置
                    if(s[cur_x][cur_y] == '-') break;//注意中间不能有空位!!
                    if(s[cur_x][cur_y] != now) {
                        far_x = cur_x;
                        far_y = cur_y;
                    }
                    cur_x += dir[k][0];
                    cur_y += dir[k][1];
                }
                if(far_x != -1) {//没有异色棋子
                    // cout << far_x << far_y << endl;
                    cur_x = x + dir[k][0];
                    cur_y = y + dir[k][1];
                    while(cur_x >= 0 && cur_x < n && cur_y >= 0 && cur_y < n) {
                        if(cur_x == far_x && cur_y == far_y) break;
                        if(!last[cur_x][cur_y]) {//如果上一轮没有动过颜色,就反转颜色
                            if(s[cur_x][cur_y] != '-') {
                                last[cur_x][cur_y] = true;
                                current[cur_x][cur_y] = true;
                                if(s[cur_x][cur_y] == 'w') s[cur_x][cur_y] = 'b';
                                else if(s[cur_x][cur_y] == 'b') s[cur_x][cur_y] = 'w';
                            }
                        }
                        cur_x += dir[k][0];
                        cur_y += dir[k][1];
                    }
                }
            }
            last = current;
            if(now == 'w') now = 'b';
            else now = 'w';
            for(int i = 0; i < n; i++) cout << s[i] << endl;
            cout << endl << endl;
        }
        for(int i = 0; i < n; i++) cout << s[i] << endl;
        cout << "END" << endl;

    }

    return 0;
}


第三题 消灭敌人

给定地图有a个人消灭b个敌人,第i个人每次可以走v[i]步,不能穿过墙和敌人,除非最后一步是敌人(最后一步是敌人就消灭)。求消灭所有敌人最短步数。

还是准备暴力搜索,结果超时,无解

#include <bits/stdc++.h>
using namespace std;

int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

struct Node {
    int x, y, step;
    Node() {
        step = 0;
    }
};

int ans;
bool vis[11][21][21];
int n, m, a, b;

void dfs(vector<string> &s, vector<int> &v, int b, int step, vector<Node> &person, int index) {
    if(b == 0) {
        ans = min(ans, step);
        return;
    }
    if(step >= ans) return;
    if(index != -1) {
        int i = index;
        for(int k = 0; k < 4; k++) {
            int next_x = person[i].x + dir[k][0];
            int next_y = person[i].y + dir[k][1];
            if(next_x >= 0 && next_x < n && next_y >= 0 && next_y < m && s[next_x][next_y] != 'W' && !vis[i][next_x][next_y]) {
                vis[i][next_x][next_y] = true;
                int pre_x = person[i].x;
                int pre_y = person[i].y;
                person[i].x = next_x;
                person[i].y = next_y;
                person[i].step++;

                int next_b = b;
                if(s[next_x][next_y] == 'E' && person[i].step % v[i] == 0) {
                    next_b--;
                    s[next_x][next_y] = '+';
                }
                if(person[i].step % v[i] == 0) {
                    dfs(s, v, next_b, step + 1, person, -1);
                } else {
                    dfs(s, v, next_b, step + 1, person, index);
                }

                person[i].step--;

                if(next_b != b) {
                    s[next_x][next_y] = 'E';
                }
                person[i].x = pre_x;
                person[i].y = pre_y;
                vis[i][next_x][next_y] = false;
            }
        }
    }
    for(int i = 0; i < a; i++) {
        for(int k = 0; k < 4; k++) {
            int next_x = person[i].x + dir[k][0];
            int next_y = person[i].y + dir[k][1];
            if(next_x >= 0 && next_x < n && next_y >= 0 && next_y < m && s[next_x][next_y] != 'W' && !vis[i][next_x][next_y]) {
                vis[i][next_x][next_y] = true;
                int pre_x = person[i].x;
                int pre_y = person[i].y;
                person[i].x = next_x;
                person[i].y = next_y;
                person[i].step++;

                int next_b = b;
                if(s[next_x][next_y] == 'E' && person[i].step % v[i] == 0) {
                    next_b--;
                    s[next_x][next_y] = '+';
                }
                if(person[i].step % v[i] == 0) {
                    dfs(s, v, next_b, step + 1, person, -1);
                } else {
                    dfs(s, v, next_b, step + 1, person, i);
                }
                person[i].step--;

                if(next_b != b) {
                    s[next_x][next_y] = 'E';
                }
                person[i].x = pre_x;
                person[i].y = pre_y;
                vis[i][next_x][next_y] = false;
            }
        }
    }
}

int main() {

    int T;
    cin >> T;
    while(T--) {
        cin >> n >> m >> a >> b;
        vector<int>v(a);
        for(int i = 0; i < a; i++) {
            cin >> v[i];
        }
        vector<string>s(n);
        vector<Node>person(a);
        memset(vis, false, sizeof(vis));

        for(int i = 0; i < n; i++) {
            cin >> s[i];
            for(int j = 0; j < s[i].size(); j++) {
                if(isdigit(s[i][j])) {
                    person[s[i][j] - '0'].x = i;
                    person[s[i][j] - '0'].y = j;
                    vis[s[i][j] - '0'][i][j] = true;
                }
            }
        }
        ans = INT_MAX;
        dfs(s, v, b, 0, person, -1);
        if(ans == INT_MAX) cout << -1 << endl;
        else cout << ans << endl;
    }

    return 0;
}

/*

2
1 10 1 1
4
0++++E++++
4 4 2 2
4 4
0++1
EWW+
+WW+
+E++
*/




#网易笔试##笔经##网易#
全部评论
第三题应该是多源bfs,复杂度是n*m*4的那种
点赞 回复 分享
发布于 2022-03-25 10:27
这代码量怎么都这么多
点赞 回复 分享
发布于 2022-03-20 16:26
第三题应该是bfs+最优匹配
点赞 回复 分享
发布于 2022-03-17 22:35
看这第三题代码量,幸亏我果断放弃去调前面的题去了
点赞 回复 分享
发布于 2022-03-17 22:23
第二题题目意思有中间必须连续吗??? 我以为八个方向所有可以达到的棋子。。。
点赞 回复 分享
发布于 2022-03-17 22:22
我看第一题太麻烦了,就去做第二第三题了,第二题搞完,去第三题也是用暴搜做,结果TLE了😅,心态崩了,最后第一题的时间也没了
点赞 回复 分享
发布于 2022-03-17 22:18
第一题每行要输出string?这么操蛋的吗
点赞 回复 分享
发布于 2022-03-17 22:17

相关推荐

从小父母离异家里没人管,靠着心里的不安和学校的环境也算是坚持到了学有所成的地步。到了大学环境开始松散不知道该做什么,只觉得在不挂科的基础上能往上考多少就考多少,等到秋招来临才发现自己有多么幼稚无能,今年九月份初才发现自己原来连一个求职的方向都没有。因为之前做过前后端一体的课设,算是有过了解,而对于其他岗位连做什么都不知道,因此这一个半个月在越来越焦虑的同时埋头苦学,事到如今想要活下去我似乎只能走前端这条路了,9月初先是靠着虚假夸大能力的简历得到一些笔试来确定了考察的方向,有一个大厂的无笔试面试最终是拒绝了没有勇气去面对。然后在这个基础上埋头苦学,如今也算是搭好了自己前端学习的框架和思考的瞄,可以逐渐给自己扩展新的知识和能力了,但这并不是一件多好的事儿,因为我发现学的越多越焦虑,学的越多便越无力。因为我感觉我如今努力学习的知识都是竞争对手们早就掌握了的东西,我如今困惑追求答案的难题早就被别人解决。别人早就能得心应手地做出项目而我连思考都会卡壳,看着别人的笔试和面经上那些闻所未闻的题目,我才知道别人到底有多强而我有多幼稚,我什么时候才能达到别人那种堪称熟练的能力呢?而且网上的焦虑越多越多,即便是真有这么高的能力最后也大概落得一个低薪打工人的下场,我真的感到迷茫。秋招都快结束了,而我还在继续痛苦的学习之旅,这些天找前端面试发现似乎问的有些简单跟网上搜到的内容不符(可能因为并不是大厂),我是不是本来就没打算被招所以别人懒得细问呢?我不知道,我只能继续总结下去学习下去,不管如何我都要活下去,如果我能早一些准备就好了,如果暑假能意识到现在这个情况就好了,可惜没有如果。种下一棵树的最好时间是十年前,其次是现在,虽然我相信自己的学习能力,但已经错过了最好的时机,只能在焦虑与痛苦中每天坚持学下去。目前的路还有很长很长,先去把typescript看了,再去巩固vue3的基础,再去练习elementui的使用,如果这能找到实习的话就好了。接下来呢?去学uniapp和小程序,不管如何我都要对得起曾经努力的自己。即便我们都感到痛苦,但我心中还是希望我们都能靠自己的努力来获取自己想要的幸福。
紧张的牛牛等一个of...:在担心什么呢,有一手985的学历在,就算是小厂别人都会要的,咱们双非的人更多,多少还在沉沦的,怕什么了
一句话证明你在找工作
点赞 评论 收藏
分享
评论
6
39
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务