题目
解题思路
这道题可以直接用广度优先搜索做,但是在比赛的时候,并没有做这道题,遗憾,只拿了10分打表分。因题目确保只有九个数,那么可以将这些160到179的数化成1到9,即方便了判重,也避免了数组越界。然后就执行(left 和 right)的命令,注意细节即可。
//这道题还可以用最短路做,将每种状态化作9进制数,然后每个数(点)之间求最短路。
代码(广度优先搜索+哈希)
#include<cstdio>
#include<map>
#include<algorithm>
#include <iostream>
using namespace std;
map<int,bool>w;
int n,mid,q,d,a[10][362881],b[10],c[10],fa[362881],head,tail;
int fdd()
{
int answ=0; //组合成一个数
for (int i=n;i>=1;i--)
answ=answ*10+a[i][tail];
return answ;
}
bool mb()
{
bool r=true; //判断是否达到题意
for (int i=1;i<n;i++)
if (a[i+1][tail]<a[i][tail]) r=false;
if (r==false) return 0; else return 1;
}
void left()
{
int e=a[mid][head]; tail++;
for (int i=2;i<=mid;i++)
a[i][tail]=a[i-1][head];
for (int i=mid+1;i<=n;i++)
a[i][tail]=a[i][head];
a[1][tail]=e;
}
void right()
{
int e=a[mid][head]; tail++;
for (int i=n-1;i>=mid;i--)
a[i][tail]=a[i+1][head];
for (int i=mid-1;i>=1;i--)
a[i][tail]=a[i][head];
a[n][tail]=e;
}
int tgg(int x)
{
if (fa[x]!=-1) tgg(fa[x]);
d++; //回溯
return d;
}
int main()
{
scanf("%d",&n);
mid=(1+n)/2;
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),c[i]=b[i];
sort(c+1,c+n+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (c[i]==b[j]) {b[j]=i; break;}
for (int i=1;i<=n;i++)
a[i][1]=b[i];
head=0; tail=1; fa[1]=-1;
do
{
head++;
left(); q=fdd();
if (mb())
{
printf("%d",tgg(head));
return 0;
}
if (!w[q])
{
fa[tail]=head;
w[q]=1;
} else tail--;
right(); q=fdd();
if (mb())
{
printf("%d",tgg(head));
return 0;
}
if (!w[q])
{
fa[tail]=head;
w[q]=1;
} else tail--;
}while (head<tail); //主过程
puts("No Answer");
}