暴力演算法
阿新 • • 發佈:2020-08-03
暴力演算法
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; }