楼主的做法是先保证 上下和 <= 左右和 <= 前后和,再保证 上下中最小的数 < 左右中最小的数 < 前后中最小的数 再保证 上 < 下 左 < 右。此时形状相同的每个骰子必被归到同一状态。
然后算上下和,左右和,前后和 如果此时前 < 后就取前后和,否则取负数
然后用个大于22的数为base来编码这三个数。比如f(x) = a_{上下和} * 900 + a_{左右和} * 30 + a_{前后和},可以保证是唯一映射
然后用个哈希映射算size,排序就完事了。注意如果相对的两数交换位置的话必须有另一对相对的数交换位置。如果要交换两组相对的数,要swap三次,想不明白可以画图看看。
#include <bits/stdc++.h> using namespace std; void myswap(int& i, int &j) { int t = i; i = j; j = t; } int main(void) { int N, a1, a2, b1, b2, c1, c2, d1, d2, d3, m1, m2, m3; cin >> N; unordered_map<int, int> us; for(int i = 0; i < N; ++i) { cin >> a1 >> a2 >> b1 >> b2 >> c1 >> c2; // shang xia zuo you qian hou if(a1 + a2 > b1 + b2) { myswap(a1, b1); myswap(a2, b2); myswap(b1, b2); } if(a1 + a2 > c1 + c2) { myswap(a1, c1); myswap(a2, c2); myswap(c1, c2); } if(b1 + b2 > c1 + c2) { myswap(b1, c1); myswap(b2, c2); myswap(c1, c2); } m1 = (a1 < a2 ? a1 : a2); m2 = (b1 < b2 ? b1 : b2); m3 = (c1 < c2 ? c1 : c2); if(m1 > m2) { myswap(a1, b1); myswap(a2, b2); myswap(b1, b2); } if(m1 > m3) { myswap(a1, c1); myswap(a2, c2); myswap(c1, c2); } if(m2 > m3) { myswap(b1, c1); myswap(b2, c2); myswap(c1, c2); } if(a1 > a2) { myswap(a1, a2); if(b1 > b2) { myswap(b1, b2); } else { myswap(c1, c2); } } else if(b1 > b2) { myswap(b1, b2); myswap(c1, c2); } if(a1 > a2) { myswap(a1, a2); if(b1 > b2) { myswap(b1, b2); } else { myswap(c1, c2); } } if(b1 > b2) { myswap(b1, b2); myswap(c1, c2); } d1 = a1 + a2; d2 = b1 + b2; d3 = (c1 > c2 ? c1 + c2 : -c1 - c2); int hashval = d1 * 900 + d2 * 30 + d3; ++us[hashval]; } vector<int> v; for(auto &x: us) { v.emplace_back(x.second); } cout << us.size() << '\n'; sort(v.begin(), v.end(), greater<int>()); cout << v[0]; for(int i = 1; i < v.size(); ++i) { cout << ' ' << v[i]; } cout << '\n'; return 0; }
全部评论
(1) 回帖