CF442A Borya and Hanabi
目录
- 题目
- 算法标签: 枚举, 位运算优化, 模拟
- 思路
- 代码
题目
CF442A Borya and Hanabi
算法标签: 枚举, 位运算优化, 模拟
思路
注意到, 颜色数量和数字数量都是 5 5 5, 因此可以使用位运算枚举需要选择的颜色数量和数字数量, 如果能将所有牌覆盖到, 那么当前方案就是一个合法的方案可以更新 a n s ans ans, 但是因为牌是可能有重复的, 需要开一个 s e t set set对牌进行去重, 需要将二维信息映射到一维, 也就是 a × 10 + b a \times 10 + b a×10+b每一种牌生成唯一的哈希值, 然后枚举所有的颜色和数字的选择情况
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <set>
using namespace std;
const int M = 1 << 5, INF = 0x3f3f3f3f;
int get(int x) {
int ans = 0;
for (int i = 0; i < 5; ++i) {
ans += x >> i & 1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
map<char, int> mp;
mp['R'] = 0;
mp['G'] = 1;
mp['B'] = 2;
mp['Y'] = 3;
mp['W'] = 4;
set<int> st;
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
int col = mp[s[0]];
int val = s[1] - '1';
st.insert(col * 10 + val);
}
n = st.size();
int ans = INF;
// 枚举所有颜色选择情况
for (int i = 0; i < M; ++i) {
// 枚举所有数字选择情况
for (int j = 0; j < M; ++j) {
set<int> vis;
// 枚举所有牌
for (auto &x : st) {
int curr = 0;
int col = x / 10;
int val = x % 10;
if (i >> col & 1) {
curr += (col + 1) * 10;
}
if (j >> val & 1) {
curr += val + 1;
}
vis.insert(curr);
}
if (vis.size() == n) {
int cnt = get(i) + get(j);
ans = min(ans, cnt);
}
}
}
cout << ans << "\n";
return 0;
}