六月集训(第17天)—广度优先搜索

广度优先搜索

1. 2059. 转化数字的最小运算数

    思路:
        用数组中的数对start进行三种不同的操作,获得0~1000之间的数字,找到结果后返回。时间复杂度$O(n * C)$, $C = 1000$生成数字的范围。

struct MY_NUM {
    int num;
    int step;
};

class Solution {
public:
    int minimumOperations(vector<int>& nums, int start, int goal) {
        int nums_size = nums.size(), i;
        queue<MY_NUM> q;
        bool vis[1010];
        memset(vis, 0, sizeof(vis));
        q.push({start, 0});
        vis[start] = true;
        while (!q.empty()) {
            MY_NUM now = q.front();
            q.pop();
            for (i = 0; i < nums_size; ++i) {
                int temp = now.num + nums[i];
                if (temp == goal) return now.step + 1;
                if (temp >= 0 && temp <= 1000 && !vis[temp]) {
                    vis[temp] = true;
                    q.push({temp, now.step + 1});
                }
                temp = now.num - nums[i];
                if (temp == goal) return now.step + 1;
                if (temp >= 0 && temp <= 1000 && !vis[temp]) {
                    vis[temp] = true;
                    q.push({temp, now.step + 1});
                }
                temp = now.num ^ nums[i];
                if (temp == goal) return now.step + 1;
                if (temp >= 0 && temp <= 1000 && !vis[temp]) {
                    vis[temp] = true;
                    q.push({temp, now.step + 1});
                }
            }
        }
        return -1;
    }
};

2. 690. 员工的重要性

    思路:
        利用unordered_map将id直接映射该员工的信息结点指针,方便查询。利用队列搜索每个员工的员工,搜过过程中累加重要性。

/*
// Definition for Employee.
class Employee {
public:
    int id;
    int importance;
    vector<int> subordinates;
};
*/

class Solution {
public:
    int getImportance(vector<Employee*> employees, int id) {
        queue<int> q;
        unordered_map<int, Employee*> worker;
        int n = employees.size(), i;
        int ans = 0;
        for (i = 0; i < n; ++i) {
            worker[employees[i]->id] = employees[i];    // 用id直接映射该员工的信息结点指针
        }
        ans += worker[id]->importance;
        q.push(id);
        while (!q.empty()) {
            int now_id = q.front();
            q.pop();
            int new_id;
            int now_size = worker[now_id]->subordinates.size(), j;
            for (j = 0; j < now_size; ++j) {
                new_id = worker[now_id]->subordinates[j];
                Employee *temp = new Employee();
                temp = worker[new_id];
                ans += temp->importance;    //  累加重要性
                q.push(new_id); // 将now_id的直属员工加入队列
            }
        }
        return ans;
    }
};

3. 672. 灯泡开关 Ⅱ

    思路:
        利用数学方法找规律:一共有四种方法,之间可以相互组合
        首先讨论四种方法之间的组合:
            某种操作出现奇数次相当于出现1次,出现偶数次相当于没有出现
            AB == C AC == B BC == A
            1) presses = 0 操作0次只能有全灭一种情况
            2) presses = 1 操作一次有 A B C D四种情况
            3) presses = 2 前三种操作出现的组合只有 0 A B C 共四种种情况,加上第四种操作,总的操作可能有 0 A B C D AD BD CD共八种可能。

        下面分类讨论
            (1) n == 0 ,ans = 1
            (2) n == 1 ,ans = 2
            0 1
            (3) n == 2
            此时A, C, D的效果相同都是让i==1位置上的灯翻转
              3.1) presses == 1 ans = 3;
              不能实现全灭
              3.2) presses >= 2 ans = 4;
            (4) n >= 3
              4.1) presses == 1 ans = 3;
              A B C D四种情况
              4.2) presses == 2 ans = 7;
              0 A B C AD BD CD此时无法通过组合实现单纯的D情况,共七种情况;
              4.3) presses == 3 ans = 8;
              0 A B C D AD BD CD八种情况均可以组合获得。

class Solution {
public:
    int flipLights(int n, int presses) {
        if (presses == 0) return 1;
        if (n == 1) return 2;
        if (n == 2) {
            if (presses == 1) return 3;
            if (presses >= 2) return 4;
        }
        if (n >= 3) {
            if (presses == 1) return 4;
            else if (presses == 2) return 7;
            else return 8;
        }
        return 1;   // n == 0
    }
};
posted @ 2022-06-17 13:49  番茄元  阅读(23)  评论(0)    收藏  举报