序列
题目背景:
分析:迭代加深搜索
当时看到这个题的时候,手推了一个错误的贪心,然后死的很惨很惨,考场上最后十来分钟才反应过来有锅,就匆匆的又写了一个贪心,然后两个取了个min······然而最后的分数还不及大搜索。
讲讲标算,显然,每一次先把xn放到x1,然后把1 ~ n翻转,可以得到一个2 * n - 2的方案,那么我们可以利用这个上界进行搜索,然后最优化剪枝,貌似这样就有32分了,然后我们发现,每一次翻转,只会改变整个序列中的一个相邻数对,那么也就是说,对于一个相邻数对,如果两个元素之差的绝对值是大于1的,那么一定需要至少一次操作才能满足条件,那么我们发现既然有上界,那么我们可以选择迭代加深,并且可以用需要修改的相邻数对的个数作为估价来进一步剪枝,总之复杂度O(能过)
Source:
/*
created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <ctime>
#include <bitset>
inline char read() {
static const int IN_LEN = 1024 * 1024;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}
///*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = read(), iosig = false; !isdigit(c); c = read()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void W(T x) {
static int buf[30], cnt;
if (x == 0) write_char('0');
else {
if (x < 0) write_char('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) write_char(buf[cnt--]);
}
}
inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}
/*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = getchar(), iosig = false; !isdigit(c); c = getchar())
if (c == '-') iosig = true;
for (x = 0; isdigit(c); c = getchar())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
const int MAXN = 25;
int n, t, ans, step;
int a[MAXN], b[MAXN];
inline int check() {
int ret = 0;
for (int i = 2; i <= n; ++i) if (abs(a[i] - a[i - 1]) > 1) ret++;
return ret;
}
inline bool dfs(int last, int cnt) {
if (cnt == step) {
bool flag = true ;
for (int i = 1; i <= n; ++i) if (a[i] != i) flag = false;
return flag;
}
if (check() + cnt > step) return false ;
for (int i = 2; i <= n; ++i) {
if (i != last) {
for (int j = 1; j <= i / 2; ++j)
std::swap(a[j], a[i + 1 - j]);
if (dfs(i, cnt + 1)) return true ;
for (int j = 1; j <= i / 2; ++j)
std::swap(a[j], a[i + 1 - j]);
}
}
return false ;
}
inline void solve() {
R(n);
for (int i = 1; i <= n; ++i) R(a[i]);
for (step = 0; step <= 2 * n - 2; ++step) {
if (dfs(0, 0)) {
ans = step;
break ;
}
}
W(ans), write_char('\n');
}
int main() {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
R(t);
while (t--) solve();
flush();
return 0;
}