【题目链接】
【思路要点】
- 随机\(K\)个起始状态,以及交换顺序,进行爬山算法,每次交换两个位置,检查是否能够让方案更优,直到达到一个局部最优解。
- 时间复杂度\(O(K\alpha N^3)\),其中\(\alpha\)为爬山算法的迭代次数,一般很小。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 105; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, x[MAXN], y[MAXN], p[MAXN], q[MAXN]; int calc() { int ans = 0, flg = 0; for (int i = 1; i <= m; i++) { ans += x[i] + y[i]; if (flg >= 1) ans += x[i]; if (flg >= 2) ans += y[i]; if (x[i] + y[i] == 10) { if (x[i] == 10) flg = 2; else flg = 1; } else flg = 0; } return ans; } int main() { read(n); for (int i = 1; i <= n; i++) read(x[i]), read(y[i]), p[i] = q[i] = i; if (x[n] == 10) { m = n + 1; p[n] = m; read(x[m]), read(y[m]); } else m = n; int finalans = 0; for (int cnt = 100; cnt >= 1; cnt--) { random_shuffle(p + 1, p + n + 1); random_shuffle(q + 1, q + n + 1); static int tx[MAXN], ty[MAXN]; for (int i = 1; i <= m; i++) { tx[i] = x[i]; ty[i] = y[i]; } for (int i = 1; i <= n; i++) { int s = p[i], t = p[q[i]]; tx[s] = x[t]; ty[s] = y[t]; } for (int i = 1; i <= m; i++) { x[i] = tx[i]; y[i] = ty[i]; } bool flg = true; int ans = calc(); while (flg) { flg = false; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) { int s = p[i], t = p[j]; swap(x[s], x[t]); swap(y[s], y[t]); int tmp = calc(); if (tmp > ans) { ans = tmp; flg = true; } else { swap(x[s], x[t]); swap(y[s], y[t]); } } } chkmax(finalans, ans); } printf("%d\n", finalans); return 0; }