序列
Description
给定一个
1
~
Data Constraint
n
<=
Solution
首先易证,做多
2n
-
2
步便可将序列转为升序序列。
由于上界较小,所以这一题可以采用迭代深搜算法。
但直接迭代深搜只有
我们可以观察出,每将序列翻转一次,只会改变一对相邻数对的差。
如果对于某个序列,它的相邻数对的差大于
1
的有
如果发现剩余步数小于
加了剪枝过掉的就是这种情况:
简直快的跟贪心一样,
unbelievable
。
从中我们可以总结出一个做搜索题的套路:
想到什么剪枝就加上去,加着加着不知不觉就变成正解了。
突然想到一句古言:“暴力出奇迹”
搜索题的时间复杂度
O
(
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,j,l) for(int i=j;i<=l;i++)
#define fd(i,j,l) for(int i=j;i>=l;i--)
using namespace std;
typedef long long ll;
const ll N=30,mo=1e7+7;
int n,m,j,k,l,i,o,p,T,zh;
int s[N];
bool dg(int o,int way,int last)
{
if(way==0&&s[1]==1)
return true;
int r[n+2],rr=way;
fo(i,1,n+1)r[i]=s[i];
fo(i,2,n)
if(i!=last){
rr=way;
rr-=(abs(r[i+1]-r[i])>1);
rr+=(abs(r[1]-r[i+1])>1);
if(rr+o+1>zh)continue;
fo(l,1,i)s[l]=r[i-l+1];
fo(l,i+1,n)s[l]=r[l];
if(dg(o+1,rr,i))return true;
}
fo(i,1,n+1)s[i]=r[i];
return false;
}
int main()
{
cin>>T;
fo(tt,1,T){
scanf("%d",&n);
fo(i,1,n)scanf("%d",&s[i]);
zh=0; s[n+1]=n+1;
fo(i,1,n)zh+=(abs(s[i+1]-s[i])>1);
int least=zh;
while(dg(0,least,0)==false)
zh++;
printf("%d\n",zh);
}
}