CF431B 题解

思路分析

答题思路

一道纯暴力题!

因为我们发现数据最大是 \(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;
}
posted @ 2023-09-10 14:03  群星之路  阅读(16)  评论(0)    收藏  举报