• 暴力算法


    暴力算法

    1. 算法分析

        很多时候题目数据量不是很大的时候都可以暴力处理。

    2. 例题

    acwing116飞行员兄弟
    题意: “飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个4х4的矩阵,您可以改变任何一个位置[i,j]上把手的状态。但是,这也会使得第i行和第j列上的所有把手的状态也随着改变。请你求出打开冰箱所需的切换把手的次数最小值是多少。
    题解: 由于按键相当于异或,因此按键的顺序无所谓。本题只有16个按键,可以直接暴力所有的情况,然后先预处理要异或的值,就可以在每次暴力的时候O(1)查询最后的结果。
    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int change[10][10];
    int state, now;
    
    int get(int x, int y) {
        return x * 4 + y;
    }
    
    int main() {
        // 预处理异或的情况
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                for (int k = 0; k < 4; ++k) 
                    change[i][j] += (1 << get(i, k)) + (1 << get(k, j));
                change[i][j] -= (1 << get(i, j));
            }
        }
        
        // state表示当前矩阵的状态
        for (int i = 0; i < 4; ++i) {
            string line;
            cin >> line;
            for (int j = 0; j < 4; ++j) {
                if (line[j] == '+') state += (1 << get(i, j));
            }
        }
        
        vector<pair<int, int> > res;
        for (int i = 0; i < 1 << 16; ++i) {  // 暴力枚举所有的状态
            vector<pair<int, int> > tmp;
            int now = state;
            for (int j = 0; j < 16; ++j) {  // 判断当前按键内每个点的状态
                if (i >> j & 1 ) {
                    int x = j / 4, y = j % 4;
                    now ^= change[x][y];
                    tmp.push_back({x, y});
                }
            }
            
            // 最后的末状态要0才能更新
            if (!now && (res.empty() || res.size() > tmp.size())) res = tmp;
        }
        
        cout << res.size() << endl;
        for (auto r: res) cout << r.first + 1 << " " << r.second + 1 << endl;
        return 0;
    }
    

    acwing1209 带分数
    题意: 100 可以表示为带分数的形式:100 = 3+ (frac{69258}{714})
    还可以表示为:100 = 82 + (frac{3546}{197})
    注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。
    类似这样的带分数,100 有 11 种表示法。
    给定n,求n的带分数的表示法数目。
    1 ≤ n < 10^6^
    题解: 1 ~ 9每个数字只能出现一次,那么全排列一共有9!种,可以暴力将9个数字拆分为abc,然后判断是否组成的带分数为n即可。时间复杂度: 9! * 9^3^
    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int res = 0;
    int n;
    vector<int> num;
    
    void check() {
        int a = 0, b = 0, c = 0;
        for (int i = 1; i <= 7; ++i) {  // a的长度
            for (int j = 1; j <= 7; ++j) {  // b的长度
                int k = 9 - i - j;  // c的长度
                if (k <= 0) continue;
                a = 0, b = 0, c = 0;
                int pos = 0;
                for (int l = 0; l < i; ++l) a = a * 10 + num[pos++];  // a
                if (a > n) continue;
                for (int l = 0; l < j; ++l) b = b * 10 + num[pos++];  // b
                for (int l = 0; l < k; ++l) c = c * 10 + num[pos++];  // c
                if (b % c == 0 && a + b / c == n) {  // 判断是否为n
                    res++;
                }
            }
        }
        return;
    }
    
    int main() {
        cin >> n;
        num.push_back(1);
        num.push_back(2);
        num.push_back(3);
        num.push_back(4);
        num.push_back(5);
        num.push_back(6);
        num.push_back(7);
        num.push_back(8);
        num.push_back(9);
        check();
        while (next_permutation(num.begin(), num.end())) check();  // 遍历全排列
        cout << res << endl;
        return 0;
    }
    
  • 相关阅读:
    JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法
    1.初识Python
    学会 Debug
    如何找出nginx配置文件的所在位置?
    一个技术人,如何做到比别人更突出
    生产环境如何快速跟踪、分析、定位问题-Java
    如何优化代码中大量的if/else,switch/case?
    UML类图几种关系的总结
    DateUtils常用方法
    如何存储和表示数字—二进制(一)
  • 原文地址:https://www.cnblogs.com/spciay/p/13428087.html
Copyright © 2020-2023  润新知