暴力算法

暴力算法

1. 算法分析

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

2. 例题

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

#include 

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 > res;
    for (int i = 0; i < 1 << 16; ++i) {  // 暴力枚举所有的状态
        vector > 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 

using namespace std;

int res = 0;
int n;
vector 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;
}

你可能感兴趣的:(暴力算法)