https://ac.nowcoder.com/acm/contest/554/I
1、考虑数字成环来移动肯定是最优的。
2、如果发现了一个环,假设环上有k个数字,那么使用k个数字中最小的数字来移动其他数字应该是较优的。
此时这个环的贡献为 环上最小值*(k-1)+环上除最小值之外的其他值。
3、但是,在第二点的基础上,一直83.3%,然后发现了,第二点并不一定是最优,你可以考虑使用环外的最小数来移动这个环上的数字,虽然多移动了一次,但是贡献有可能会更小。
此时贡献为 环上的所有值+环上的最小值+整个序列的最小值*(n+1)
4、第二点和第三点取一下min,就可以了,记得要先hash一下。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[10005], t[10005], cnt;
bool book[10005];
int has(int k)
{
return lower_bound(t, t + cnt, k) - t;
}
int main()
{
int n, MIN = 1e9;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
t[i] = a[i];
MIN = min(MIN, a[i]);
}
sort(t + 1, t + 1 + n);
cnt = unique(t + 1, t + n + 1) - t - 1;
for (int i = 1; i <= n; i++)
a[i] = lower_bound(t + 1, t + 1 + cnt, a[i]) - t;
ll ans = 0;
for (int i = 1; i <= n; i++)
{
if (book[i] == false)
{
book[i] = true;
ll sum = 0, minn = t[a[i]];
int cnt = 1;
sum += t[a[i]];
for (int j = a[i]; j != i; j = a[j])
{
book[j] = true;
sum += t[a[j]];
minn = min(minn, 1LL * t[a[j]]);
cnt++;
}
if (cnt != 1)
ans += min(sum + minn * (cnt - 2), minn + sum + (cnt + 1) * MIN);
}
}
printf("%lld", ans);
}