• 【Uva11212】 Editing a Book(IDA*)


    【题意】

      有n个数字的全排列,每次可以剪切一段粘贴到某个位置。问最后变成升序最少多少步。

    如“{2,4,1,5,3,6}要2步

    {3,4,5,1,2}只要一步

    【分析】

      迭代深搜真的AC了也觉得慌= =

      【其实看到这题不应该想到宽搜么???

      全排列只有9!=362880个

      这题的IDA*的估价函数特别机智:

      n<=9,最多2需要8步,深度上限为8。

      考虑后继不正确的赎回自个数h,可以证明每次剪切时候h最多减少3,因此当3*d+h>3*maxd时可以剪枝。

      【证明上面那个画一下就知道,一次复制粘贴只有3个东西的后继被影响。【机智ORZ  ....  

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<cmath>
     8 using namespace std;
     9 #define Maxn 15
    10 
    11 int a[Maxn][Maxn],v[Maxn];
    12 int maxd,n;
    13 bool ok;
    14 
    15 bool ffind(int x,int h)
    16 {
    17     if(x==maxd)
    18     {
    19         if(h!=0) return 0; 
    20         ok=1;return 1;
    21     }
    22     if(3*x+h>3*maxd) return 0;
    23     for(int i=1;i<=n;i++)
    24      for(int j=i;j<=n;j++)
    25      {
    26         for(int k=1;k<i;k++)
    27         {
    28             for(int l=i;l<=j;l++) a[x+1][k+l-i]=a[x][l];
    29             for(int l=k;l<i;l++) a[x+1][l+j-i+1]=a[x][l];
    30             for(int l=1;l<k;l++) a[x+1][l]=a[x][l];
    31             for(int l=j+1;l<=n;l++) a[x+1][l]=a[x][l];
    32             h=0;
    33             for(int l=1;l<n;l++) if(a[x+1][l+1]!=a[x+1][l]+1) h++;
    34             
    35             ffind(x+1,h);
    36             if(ok==1) return 1;
    37         }
    38         for(int k=j+1;k<=n;k++)
    39         {
    40             for(int l=i;l<=j;l++) a[x+1][k+l-j]=a[x][l];
    41             for(int l=1;l<i;l++) a[x+1][l]=a[x][l];
    42             for(int l=j+1;l<=k;l++) a[x+1][l-j+i-1]=a[x][l];
    43             for(int l=k+1;l<=n;l++) a[x+1][l]=a[x][l];
    44             h=0;
    45             for(int l=1;l<n;l++) if(a[x+1][l+1]!=a[x+1][l]+1) h++;
    46             ffind(x+1,h);
    47             if(ok==1) return 1;
    48         }
    49      }
    50     return 0;
    51 }
    52 
    53 int main()
    54 {
    55     int kase=0;
    56     while(1)
    57     {
    58         ok=0;
    59         scanf("%d",&n);
    60         if(n==0) break;
    61         for(int i=1;i<=n;i++) scanf("%d",&a[0][i]);
    62         int h=0;
    63         for(int i=1;i<n;i++) if(a[0][i+1]!=a[0][i]+1) h++;
    64         printf("Case %d: ",++kase);
    65         for(maxd=0;maxd<=n-1;maxd++)
    66         {
    67             if(ffind(0,h)) {printf("%d",maxd);break;}
    68         }
    69         printf("
    ");
    70     }
    71     return 0;
    72 }
    View Code

    2016-11-15 09:13:56

      

  • 相关阅读:
    MapReduce教程(一)基于MapReduce框架开发<转>
    postgresql with递归
    mysql中递归树状结构<转>
    java获取上周任意一天的日期
    IBatis批量插入数据
    UI控件篇——UIPageControl及其自定义
    Android 3.0开始引入fragments(碎片、片段)类
    APACHE LOG4J™ 2
    java 反射
    PreparedStatement用途
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6064366.html
Copyright © 2020-2023  润新知