简单的BFS 和康托展开式的应用

来源:互联网 发布:第二代身份证照片软件 编辑:程序博客网 时间:2024/05/02 06:02

Description:

给n的某种排列和k,问最少次操作可以将n的这个全排列变成1~n。

每次操作可以选择连续k个数,然后将它们翻转。

Input

第一行输入一个数T,表示测试数据个数

对于每组数据,第一行输入两个数n,k,然后第二行输入n个数,为1~n的某种排列。

数据范围:(1<=k<=n<=8)

Output

对于每组数据输出一个数,表示最少的操作次数,如果无法完成,输出-1.

Sample Input

3

3 3

1 2 3

3 3

3 2 1

5 4

3 2 4 5 1

Sample Output

0

1

-1

思路分析:1.最少的步骤数,很容易想到BFS,

                   2.主要是 状态如何存储,最多有8!=40320个排列,可以用康托展开式来存储,n!个排列对应数0-n!-1,就很方便记忆状态了

注意:1.queue用之前要清空

#include<iostream>#include<cstdio>#include<queue>#include<memory.h>using namespace std;int n,k;struct node{    int arr[9];    int step;};bool flag[100000];queue<node>q;int fun(int x)//求阶乘{    if(x==1||x==0)        return 1;    else    {         int sum=1;         for(int i=x;i>=1;i--)            sum*=i;         return  sum;    }}int cantor(node x)//求康托相对应的数{    int sum=0;    /*for(int i=1;i<=n;i++)        printf("%d**",x.arr[i]);*/    for(int i=1;i<=n;i++)    {        int temp=0;        for(int j=i+1;j<=n;j++)            if(x.arr[j]<x.arr[i])                temp++;        sum+=temp*fun(n-i);    }    //printf("sum=%d\n",sum);    return sum;}void inline swap(int &x,int &y){    int temp=x;    x=y;    y=temp;}node shift(node x,int i){    for(int j=1;j<=k/2;j++)        swap(x.arr[i+j-1],x.arr[i+k-1-j+1]);    return x;}int main(){    int T;    node a;    scanf("%d",&T);    while(T--)    {        memset(flag,0,sizeof(flag));        int ans=0;        scanf("%d %d",&n,&k);        for(int i=1;i<=n;i++)            scanf("%d",&a.arr[i]);        a.step=0;        while(!q.empty())//忘了清空队列            q.pop();        q.push(a);        /*for(int i=1;i<=n;i++)            printf("%d   ",a.arr[i]);*/        int x=cantor(a);        //printf("x=%d\n",x);        flag[x]=1;        if(x==0)           {               printf("0\n");               continue;           }        int ok=0;        while(!q.empty())        {            node temp=q.front();            q.pop();            for(int i=1;i<=n-k+1;i++)//弄成i-k+1            {                node t=shift(temp,i);                t.step=temp.step+1;                x=cantor(t);                if(x==0)                {                    ok=1;                    ans=t.step;                    break;                }                if(flag[x]==1)//出现过的状态 标记一下,避免再次遍历                    continue;                else                {                    flag[x]=1;                    q.push(t);                }            }            if(ok==1)                break;        }        if(ok==0)           ans=-1;        printf("%d\n",ans);    }    return 0;}



 


原创粉丝点击