先评测数据是1<= n <= 10,最多也只能9支队伍,大思路上由小到大遍历队伍数量(1),对于每个队伍数量再进行判断,用向量容器v[N]储存每一种配队情况。 由1到cnt遍历每种配对情况,用num暂存当前深度要加入队伍的值(2),再用容器 j 遍历当前队伍的每一个值,互相判断有无倍数关系(3)。 若有则直接剪枝跳出这次i(4),说明v[i]的配队方式已经失去了可能性;若无则push_back这个成员加入到v[i]配对中,说明可行,并进入到下一层深度中(5)看下一层(或更深层次)是否可行。 若后续层数不可行,则当前cnt支队伍的方案仍失效,在遍历下一个cnt支队伍方案前,进行回溯(5),把上一个push进去的pop出来,再进入下个cnt判断,并如是循环。 最后只要把1-10支队伍都遍历一遍,返回第一个dfs为true即为最小队伍数。
#include <iostream>
#include <vector>
using namespace std;
const int N = 15;
int a[N], n;
vector<int> v[N];
//cnt表示队伍数量,dfs返回cnt支队伍情况下是否成功分组
bool dfs(int cnt,int dep)
{
if(dep == n + 1)
{
return true;
}
int num = a[dep]; // **(2) **
for(int i = 1;i <= cnt; ++i)
{
bool tag = true;
for(const auto &j : v[i])if(j % num == 0 || num % j == 0) tag = false; // **(3)**
if(!tag) continue; //**(4)**
v[i].push_back(num);
if(dfs(cnt, dep + 1)) return true;// **(5)**
v[i].pop_back();
}
return false;
}
int main()
{
cin >> n; for(int i = 1;i <= n; ++i) cin >> a[i];
for(int i = 1;i <= 10; ++i)
{
if(dfs(i , 1)) // **(1)**
{
cout << i << '\n';
break;
}
}
return 0;
}