思路分析
答题思路
一道纯暴力题!
因为我们发现数据最大是 \(5\),而枚举全排列的时间复杂度为 \(\mathcal O(n!)\),对于这种极小的数据范围是丝毫不用顾虑的,因为我们只需要执行 \(120\) 次。
如何快速求出一个数组的全排列?
我们可以使用 dfs,一层一层获取这个数组的全排列。
但是 STL 大法可是 C++ 党的福利,不用白不用。
在 STL 中,有一个函数 next_permutation()
,可以枚举一个数组的全排列,但是时间复杂度高达 \(O(n!)\),在 \(1\) 秒内最多只能枚举长度为 \(11\) 的数组的全排列。
因为这次最大的长度为 \(5\),所以是不会超时的。
敲响警钟:一开始的数组必须是升序排列的,否则程序运行结果就会出现问题!
更多了解见这里。
如何计算一种方法的幸福度?
我们只需按照题目进行模拟即可,题目中已经有明显的示例了,这里不再多言。
复杂度分析
next_permutation()
的时间复杂度是 \(\mathcal O(n!)\),计算幸福度的时间复杂度是 \(O(1)\) 的,所以最终的时间复杂度是 \(\mathcal O(n!)\) 的。
程序实现
#include <bits/stdc++.h>
using namespace std;
int ans = INT_MIN, g[6][6], a[6] = {0, 1, 2, 3, 4, 5}; // ans要赋很小的值,才能求出最大值!
int main() {
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 5; j++)
cin >> g[i][j]; // 读入
do ans = max(ans, g[a[1]][a[2]] + g[a[2]][a[1]] + g[a[2]][a[3]] + g[a[3]][a[2]] + 2 * g[a[3]][a[4]] +
2 * g[a[4]][a[3]] + 2 * g[a[4]][a[5]] + 2 * g[a[5]][a[4]]);
// 计算幸福度,只需模拟题意
while (next_permutation(a + 1, a + 6)); // 枚举全排列,后面一项本为a+5+1,简写为a+6
cout << ans;
return 0;
}
标签:排列,题解,复杂度,CF431B,枚举,数组,ans,mathcal
From: https://www.cnblogs.com/IShallReturn/p/CF431B-ti-jie.html