8.8 竞技世界 笔试真题 个人题解记录

第一题 收大白菜

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;

int N;
vector<int> val;
// 基于邻接表的有向图
vector<vector<int>> graph;
// 结果数组,能收的最大白菜数量,当前节点,当前收的白菜数量,当前走过的点
void dfs(vector<int>& res, int& iMax, int st, int tem, vector<int>& cur){
    tem += val[st];
    cur.push_back(st);
    //  没有路可走
    if(graph[st].size() == 0){
        if(tem > iMax){
            iMax = tem;
            res = cur;
        } else if(tem == iMax) {
            // 当收的白菜的个数相等时,判断下标的大小,因为数组里面存放的都是下标,直接求和比较即可
            int tot1 = accumulate(res.begin(), res.end(), 0);
            int tot2 = accumulate(cur.begin(), cur.end(), 0);
            if(tot1 > tot2) res = cur;
        }
    }
    // DFS 深搜
    for(int i=0; i<graph[st].size(); i++)
        dfs(res, iMax, graph[st][i], tem, cur);

}
int main(){
    cin >> N;
    // 为了不进行下标的转换,直接多开一维
    val.resize(N+1);
    graph.resize(N+1);
    for(int i=1; i<=N; i++)
        cin >> val[i];
    int tem = 0;
    for(int i=1; i<N; i++)
        for(int j=i+1; j<=N; j++){
            cin >> tem;
            // 如果为 1 代表有一条路,直接存放下标
            if(tem == 1) graph[i].push_back(j);
        }

    vector<int> res;
    vector<int> cur;
    int iMax = 0;
    // dfs 大法好
    dfs(res, iMax, 1, 0, cur);
    cout << iMax << endl;
    for(int i=0; i<res.size()-1; i++)
        cout << res[i] << ' ';
    cout << res.back() << endl;
    return 0;
}

第二题 发工资

大于 50 的部分肯定得优先发 50 100 的,所以先算一下 50 一下的最优解法,后面直接代入即可
想了一下 大于 5 的好像就优先发 大于5的,这块儿还能更加简化一下

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int n;
    cin >> n;
    vector<int> val(n, 0);
    for(auto &it:val)
        cin >> it;
    int iMax = *max_element(val.begin(), val.end());
    vector<int> coins{1, 2, 5, 10, 20, 50, 100};
    // 大于 50 的部分肯定是得 50 100 的发
    vector<int> dp(51, 51);
    dp[0] = 0;
    for(int i = 1; i<=min(iMax, 50); i++)
        for(int j=0; j<coins.size() && i >= coins[j]; j++)
            dp[i] = min(dp[i], dp[i-coins[j]] + 1);

    int res = 0;
    for(auto &it:val){
        res += it/100;
        it %= 100;
        res += it/50 + dp[it%50];
    }
    cout << res << endl;
    return 0;
}

优化后的代码,应该能过,不太确定

#include <iostream>
using namespace std;
int main(){
    int n, val, res = 0;
    cin >> n;
    vector<int> coins{100, 50, 20, 10, 5, 2, 1};
    for(int i=0; i<n; i++){
        cin >> val;
        // 每次把当前面额的钱发到发不出为止
        for(auto &i:coins){
            res += val/i;
            val %= i;
        }
    }

    cout << res << endl;
    return 0;
}

第三题 扫雷

吐槽一下,这个备注 1 是不是用来迷惑人的
先写一个方法可以快捷算出周围雷的数量,然后根据逻辑更新一下即可

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int getNum(vector<vector<char>>& grid, int x, int y){
    int res = 0;
    // 两层 for 循环,来算出当前方格周围雷的数量
    for(int i = max(0, x-1); i < min(x+2, (int)grid.size()); i++)
        for(int j = max(0, y-1); j < min(y+2, (int)grid[i].size()); j++){
            if(i == x && j == y) continue;
            if(grid[i][j] == 'M') res++;
        }
    return res;
}
void helper(vector<vector<char>>& grid, int x, int y){
    // 判断边界
    if(x < 0 || y < 0 || x >= grid.size() || y >= grid[x].size()) return;
    // 当前为雷,或者已经走过了,退出
    if(grid[x][y] == 'M' || grid[x][y] != 'E') return ;
    int num = getNum(grid, x, y);
    if(num != 0) {
        // 当前周围有雷,只更新当前点,停止递归
        grid[x][y] = '0' + num;
        return ;
    }
    // 当前周围没有雷,更新当前点,继续递归
    grid[x][y] = 'B';
    helper(grid, x+1, y);
    helper(grid, x-1, y);
    helper(grid, x, y+1);
    helper(grid, x, y-1);
}
int main(){
    vector<vector<char>> grid(4,vector<char>(5));
    for(int i=0; i<4; i++)
        for(int j=0; j<5; j++)
            cin >> grid[i][j];
    int x, y;
    cin >> x >> y;
    // 当前是雷, 直接凉
    if(grid[x][y] == 'M') grid[x][y] = 'X';
    else{
        int num = getNum(grid, x, y);
        // 雷的数量为 0 时,才会进入 DFS
        if(num == 0) helper(grid, x, y);
        else grid[x][y] = '0' + num;
    }
    // 打印输出
    for(auto &it:grid){
        for(auto &i:it)
            cout << i;
        cout << endl;
    }
    return 0;
}
#竞技世界##笔试题目##题解##春招#
全部评论
校友…… 为啥只能用cpp🤣🤣
点赞 回复
分享
发布于 2019-08-08 21:14

相关推荐

点赞 评论 收藏
转发
4 15 评论
分享
牛客网
牛客企业服务