1.题目描述:点击打开链接
2.解题思路:本题利用暴力搜索,逐个枚举排列的起始位置,然后分顺时针,逆时针两种情况将杂乱的排列变成有序的环状排列。比如需要将1 2 4 3变成从位置2(范围是0~n-1)开始的顺时针排列(即把它变成3 4 1 2,数字1从位置2开始),那么如果1在原排列中不在指定的位置2,就需要将原排列中的数字1和位于位置2的数字交换位置,以此类推,有点像中学时候的排座位,大家保持原位置不动时,老师自己点名指定谁和谁换位置。然后用best统计交换次数最小的那个值即可。注意:本题不要只找需要交换的次数而没有实际交换,这样会一直WA,虽然我目前也不太清楚原因==
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define maxn 500+10
int a[maxn], pos[maxn];
int n;
int compare(int p,int turn)//计算需要交换的次数
{
int ta[maxn], tp[maxn];
int cnt, j = p;
memcpy(ta, a, sizeof(a));
memcpy(tp, pos, sizeof(pos));
if (turn == 1)
{
cnt = 0;
for (int i = 1; i <= n; i++)//以p位置为起点,将ta逐步变成顺时针排列,j相当于标准位置,每个i都要填到j指定的位置
{
int temp = tp[i];
if (temp != j)
{
cnt++;
tp[ta[temp]] = j; tp[ta[j]] = temp;
swap(ta[temp], ta[j]);
}
j++; if (j == n)j = 0;
}
return cnt;
}
else
{
cnt = 0;
for (int i = 1; i <= n; i++)//将ta变成p位置为起点的逆时针队列
{
int temp = tp[i];
if (temp!=j)
{
cnt++;
tp[ta[temp]] = j; tp[ta[j]] = temp;
swap(ta[temp], ta[j]);
}
j--; if (j == -1)j = n - 1;
}
return cnt;
}
}
int main()
{
//freopen("test.txt", "r", stdin);
while (scanf("%d", &n) != EOF&&n)
{
memset(a, 0, sizeof(a));
memset(pos, 0, sizeof(pos));
for (int i = 0; i < n; i++)
{
scanf("%d", a + i);
pos[a[i]] = i;
}
int best = 999999999;
int cnt = 0;
for (int i = 0; i < n; i++)
{
best = min(best, compare(i,1));
best = min(best, compare(i,-1));
}
printf("%d\n", best);
}
return 0;
}