题解
一共12根木棒如果直接DFS每3根分一组复杂度非常高再乘上6000组样例直接爆炸 先使用DFS枚举状态 每次只枚举一半
12根里面选6根另外6根自然也确定了 再从6根里面选3根同理剩下三根自然也会确定 这样复杂度就会将C(12, 6)*C(6, 3)*常数
枚举出来的状态前一半处理过程中状态取反已经将后面的包含了 所以只需要用前一半即可
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e4;
int a[MAXN], p[MAXN], q[MAXN], x[MAXN], y[MAXN];
void DFS(int d, int n, int l, int t, int s, int *arr, int &cnt) //深度 总数 上取 总取 状态 存储 数量
{
if (t == n / 2)
{
arr[cnt++] = s;
return;
}
if (d == n)
return;
for (int i = l; i < n; i++)
DFS(d + 1, n, i + 1, t + 1, s | (1 << i), arr, cnt);
}
void take(int *arr, int *res, int n, int s) //按照s将状态取出
{
int pos = 0;
for (int i = 0; i < n; i++)
if (s & (1 << i))
res[pos++] = arr[i];
}
bool check(int a, int b, int c)
{
if (a + b > c && a + c > b && b + c > a)
return true;
return false;
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int pl = 0, ql = 0;
DFS(0, 12, 0, 0, 0, p, pl); //12取6状态存入p
DFS(0, 6, 0, 0, 0, q, ql); //6取3状态存入q
pl /= 2, ql /= 2; //枚举前一半状态后一半已经覆盖
int T;
cin >> T;
for (int ti = 1; ti <= T; ti++)
{
for (int i = 0; i < 12; i++)
scanf("%d", &a[i]);
vector<int> ans, vec1, vec2, vec3; //可以优化不用vector不想改了~
for (int i = 0; i < pl; i++) //枚举12选6状态
{
vec1.clear(), vec2.clear();
take(a, x, 12, p[i]);
for (int j = 0; j < ql; j++) //枚举6选3状态
{
vec3.clear();
take(x, y, 6, q[j]);
if (check(y[0], y[1], y[2]))
vec3.push_back(y[0]), vec3.push_back(y[1]), vec3.push_back(y[2]);
take(x, y, 6, ~q[j]);
if (check(y[0], y[1], y[2]))
vec3.push_back(y[0]), vec3.push_back(y[1]), vec3.push_back(y[2]);
if (vec3.size() > vec1.size())
vec1 = vec3;
}
take(a, x, 12, ~p[i]);
for (int j = 0; j < ql; j++) //枚举6选3状态
{
vec3.clear();
take(x, y, 6, q[j]);
if (check(y[0], y[1], y[2]))
vec3.push_back(y[0]), vec3.push_back(y[1]), vec3.push_back(y[2]);
take(x, y, 6, ~q[j]);
if (check(y[0], y[1], y[2]))
vec3.push_back(y[0]), vec3.push_back(y[1]), vec3.push_back(y[2]);
if (vec3.size() > vec2.size())
vec2 = vec3;
}
if (ans.size() < vec1.size() + vec2.size())
ans = vec1, ans.insert(ans.end(), vec2.begin(), vec2.end());
}
printf("Case #%d: %d\n", ti, ans.size() / 3);
for (int i = 0; i < ans.size(); i += 3)
printf("%d %d %d\n", ans[i], ans[i + 1], ans[i + 2]);
}
return 0;
}

本文介绍了一种解决12根木棒分组问题的优化算法,通过深度优先搜索(DFS)和状态枚举降低复杂度,实现高效求解。文章详细解析了代码实现过程,包括状态枚举、三角形条件检查等关键步骤。
486

被折叠的 条评论
为什么被折叠?



