翻煎饼 [迭代加深搜索+剪枝]

翻煎饼


\color{red}{正解部分}

这里有道类似的 题目

使用 迭代搜索, 最多只能跑过 n=7n=7 的数据, 需要剪枝,

每次旋转相邻数字之间的差值变化最微小, 翻转一次仅有一对数字间的差的绝对值会发生改变, 于是统计有cntcnt数字间绝对值不为 11, 则至少需要 cntcnt 次操作到终态, 依此进行剪枝 .


\color{red}{实现部分}

没什么好说的 …

#include<bits/stdc++.h>
#define reg register

const int maxn = 25;

int N;
int A[maxn];
int tmp[maxn];

bool flag;

bool chk(){
        for(reg int i = 1; i <= N; i ++)
                if(tmp[i] != i) return 0;
        return 1;
}

int chk_2(){
        int s = 0;
        for(reg int i = 1; i < N; i ++)
                if(abs(tmp[i]-tmp[i+1]) != 1) s ++;
        return s;
}

void DFS(int k, int lim){
        if(chk()){ flag = 1; return ; }
        if(k == lim+1) return ;
        if(k-1+chk_2() > lim) return ;
        for(reg int i = 1; i <= N; i ++){
                int mid = 1+i >> 1;
                std::reverse(tmp+1, tmp+i+1);
//                for(reg int j = 1; j <= mid; j ++) std::swap(tmp[j], tmp[i-j+1]);
                DFS(k+1, lim);
                std::reverse(tmp+1, tmp+i+1);
//                for(reg int j = 1; j <= mid; j ++) std::swap(tmp[j], tmp[i-j+1]);
        }
}

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]);
        for(reg int k = 1; ; k ++){
                flag = 0;
                for(reg int i = 1; i <= N; i ++) tmp[i] = A[i];
                DFS(1, k);
                if(flag){
                        printf("%d\n", k);
                        return 0;
                }
        }
        return 0;
}
posted @ 2019-07-22 20:08  XXX_Zbr  阅读(181)  评论(0编辑  收藏  举报