1. 程式人生 > 實用技巧 >排書(IDA*)

排書(IDA*)

給定n本書,編號為1-n。

在初始狀態下,書是任意排列的。

在每一次操作中,可以抽取其中連續的一段,再把這段插入到其他某個位置。

我們的目標狀態是把書按照1-n的順序依次排列。

求最少需要多少次操作。

輸入格式
第一行包含整數T,表示共有T組測試資料。

每組資料包含兩行,第一行為整數n,表示書的數量。

第二行為n個整數,表示1-n的一種任意排列。

同行數之間用空格隔開。

輸出格式
每組資料輸出一個最少操作次數。

如果最少操作次數大於或等於5次,則輸出”5 or more”。

每個結果佔一行。

資料範圍
1≤n≤15
輸入樣例:
3
6
1 3 4 6 2 5
5
5 4 3 2 1
10
6 8 5 3 4 7 2 9 1 10
輸出樣例:
2
3
5 or more

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 15 ;

int p[N];
int mc[5][N];
int T;
int n ;

int f()//估計函式
{
    int tol = 0;
    for(int i = 0; i+1 < n ; i++)
    {
        if(p[i+1] !=p[i] + 1)tol++;
    }
    return (tol +2) / 3;
}

bool dfs(int u , int depath)//當前需要的操作次數 總共能夠遍歷多少層
{
    if(u + f() > depath)  return false; 
    
    if(f() == 0) return true;
    for(int len = 1; len <= n ; len ++)
    {
        for(int l = 0 ; len + l - 1 <  n ; l ++)
        {
            int r = len + l - 1;
            for(int k = r + 1; k < n ; k++)
            {
                memcpy(mc[u], p , sizeof p);//先copy下來 便於後面回溯
                int y = l ;
                for(int x = r + 1 ; x <= k ; x ++,y ++)p[y] = mc[u][x];//用來置換替換後的位置
                for(int x = l ; x <= r; x++ , y ++ )p[y] = mc[u][x];//後半段
              
                if(dfs(u + 1, depath))return true;
                 memcpy(p, mc[u] , sizeof p);//回溯
            }
        }
    }
    
    
    return false;
    
    
}

int main()
{
    cin >> T;
    while(T--)
    {
        cin >> n ;
        for(int i = 0 ; i < n ; i ++)
        cin >> p[i];
        
         int depath = 0 ;
        while(depath < 5 && !dfs(0,depath)) ++depath;
        
        if(depath >= 5) puts("5 or more");
        else cout << depath << endl;
        
    }
    
    
    return 0;
}