链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1511
题意:
输入1~n的一个排列(3≤n≤500),每次可以交换两个整数。用最少的交换次数把排列变成1~n的一个环状排列。
分析:
莫名奇妙地AC了。。。方法是枚举起点,然后把数字逐个地安排到正确的位置。但为什么把1作为起点会错呢?
代码:
1 #include <cstdio> 2 #include <deque> 3 #include <algorithm> 4 using namespace std; 5 6 int solve(int n, deque<int> Q){ 7 int res = 0, p[500+5]; //p[i]为数字i在Q中的位置 8 for(int i = 0; i < n; i++) p[Q[i]] = i; 9 for(int i = 0; i < n; i++){ 10 if(Q[i] == i + 1) continue; 11 p[Q[i]] = p[i+1]; 12 swap(Q[i], Q[p[i+1]]); 13 res++; 14 } 15 return res; 16 } 17 18 int main(){ 19 int n; 20 while(scanf("%d", &n) && n){ 21 deque<int> Q; 22 for(int v, i = 0; i < n; i++){ 23 scanf("%d", &v); 24 Q.push_back(v); 25 } 26 int ans = 1234567890; 27 for(int i = 0; i < n; i++){ 28 Q.push_back(Q.front()); 29 Q.pop_front(); 30 ans = min(ans, solve(n, Q)); 31 } 32 reverse(Q.begin(), Q.end()); 33 for(int i = 0; i < n; i++){ 34 Q.push_back(Q.front()); 35 Q.pop_front(); 36 ans = min(ans, solve(n, Q)); 37 } 38 printf("%d\n", ans); 39 } 40 return 0; 41 }