暴力算法
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;
}