zoukankan      html  css  js  c++  java
  • 【UVA11212 算法竞赛入门经典】 Editing a Book 【IDA*】

    题意

      你有一篇由n(2<=n<=9)个自然段组成的文章,希望将它们排列成1,2,···,n。可以用剪切和粘贴来完成任务。每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴。注意剪贴板只有一个,所以不能连续剪切两次,只能剪切和粘贴交替。

    分析

      鄙人真的不擅长搜索,花了两天时间做完搜索专题的作业,然后被这一道题卡了一天,结果今下午的比赛又是搜索专题,我又不知道得补到啥时候···难受!

      这个题是比较显然的IDA*,主要是估值函数h()的计算。如果当前有res个数字的位置不正确,而每次剪切h()最多可以减少3.所以当h()>cur的时候,return false。

      然后还加了一个优化(不影响ac,但是会快不少),就是如果存在连续的一段,在cut的时候不把他们拆开。

      下面是ac的代码

     

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 const int maxn=15;
     8 int a[maxn],b[maxn];
     9 int n,kase;
    10 bool judge(){
    11     for(int i=1;i<=n;i++){
    12         if(b[i]!=i)
    13             return false;
    14     }
    15     return true;
    16 }
    17 void ope(int from,int len,int to){//将从from开始,长度为len的一段序列,复制到to位置,然后to位置到from-1位置原来的元素后延
    18     int c[maxn];
    19     for(int i=from,j=1;j<=len;i++,j++)
    20         c[j]=b[i];
    21     if(from>to){
    22         for(int i=from-1;i>=to;i--)
    23             b[i+len]=b[i];
    24         for(int i=to,j=1;j<=len;i++,j++)
    25             b[i]=c[j];
    26     }else if(from<to){
    27         for(int i=from+len;i<=to;i++)
    28             b[i-len]=b[i];
    29         for(int i=to,j=len;j>=1;i--,j--)
    30             b[i]=c[j];
    31     }
    32 }
    33 void recover(int from,int len, int to){
    34     if(from<to){
    35         ope(to-len+1,len,from);
    36     }else if(to<from){
    37         ope(to,len,from+len-1);
    38     }
    39 }
    40 
    41 bool opeti(int F,int L,int to){
    42     if(F!=1)
    43         if(b[F-1]+1==b[F])
    44           return false;
    45     if(F+L-1!=n)
    46         if(b[F+L-1]+1==b[F+L])
    47           return false;
    48     return true;
    49 }
    50 int h(){
    51     int res=0;
    52     for(int i=1;i<n;i++)
    53         if(b[i]+1!=b[i+1])res++;
    54     if(b[n]!=n)res++;
    55     return res;
    56 }
    57 
    58 bool dfs(int cur){
    59     if(cur==0){
    60         if(judge())
    61             return true;
    62         return false;
    63     }
    64     if(h()>3*cur)return false;
    65     for(int F=1;F<=n;F++){
    66         for(int L=1;L<=n-F+1;L++){
    67             for(int to=1;to<=n;to++){
    68                 if(!opeti(F,L,to))continue;
    69                 if(to==F)continue;
    70                 if(to>F&&to<=F+L-1)continue;
    71                 if(to<F&&to>=F-L+1)continue;
    72                 ope(F,L,to);
    73                 if(dfs(cur-1))
    74                     return true;
    75                 recover(F,L,to);
    76             }
    77         }
    78     }
    79     return false;
    80 }
    81 int main(){
    82  //   freopen("out.txt","w",stdout);
    83     kase=0;
    84     while(scanf("%d",&n)!=EOF&&n){
    85         for(int i=1;i<=n;i++)
    86             scanf("%d",&a[i]);
    87         for(int i=1;i<=n;i++)
    88             b[i]=a[i];
    89         int ans=0;
    90         for(int maxd=0;;maxd++){
    91             if(dfs(maxd)){
    92                 ans=maxd;
    93                 break;
    94             }
    95         }
    96         printf("Case %d: %d
    ",++kase,ans);
    97     }
    98 return 0;
    99 }
    View Code
  • 相关阅读:
    DAY1 linux 50条命令
    安卓2.0,3.0,4.0的差别
    java历史
    晶体管共射极单管放大电路
    jquery取消选择select下拉框
    oarcle数据库导入导出,创建表空间
    360chrome,google chrome浏览器使用jquery.ajax加载本地html文件
    jquery 选择器
    nodejs 相关
    关于http请求
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9427092.html
Copyright © 2011-2022 走看看