zoukankan      html  css  js  c++  java
  • UVA

    题目:

    给出n(1<n<10)个数字组成的序列,每次操作可以选取一段连续的区间将这个区间之中的数字放到其他任意位置。问最少经过多少次操作可将序列变为1,2,3……n。

    思路:

    利用IDA*来求解这个题目,首先每步操作最多可以减少3个位置错误的数字如下图(假设操作之后a、b、c都位于正确的位置)

    则启发函数可以为3*cur+h > maxd*3,其中cur是枚举到当前的操作次数,h是序列中位置不对的数字个数,maxd是枚举到的答案。

    可以用两重循环枚举选取的区间,然后枚举将其放到的位置,dfs知道序列符合题意。

    代码:

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define MAX 1000000009
    #define FRE() freopen("in.txt","r",stdin)
    #define FRO() freopen("out.txt","w",stdout)
    using namespace std;
    typedef long long ll;
    const int maxn = 10;
    int n;
    
    bool isSrot(int* buf){//判断是不是序列符合题意
        for(int i=0; i<n-1; i++){
            if(buf[i]>=buf[i+1])
                return false;
        }
        return true;
    }
    
    int ErrorNum(int* buf){//输出位置不对的数字个数
        int cnt = 0;
        for(int i=0; i<n-1; i++){
            if(buf[i]+1!=buf[i+1])
                cnt++;
        }
        return cnt;
    }
    
    void numSwap(int* buf,int* original,int s,int t,int pos){//将区间放到指定的位置
        int idx=0;
        for(; idx<pos; idx++){
            buf[idx] = original[idx];
        }
    
        for(int i=s; i<t; i++){//将操作的区间放入buf数组
            buf[idx++] = original[i];
        }
        for(int i=pos; i<n; i++){//将剩余部分补全
            if(i<s || i>=t){
                buf[idx++] = original[i];
            }
        }
    }
    
    bool dfs(int cur,int maxd,int* a){
        if(3*cur+ErrorNum(a)>3*maxd) return false;
        if(isSrot(a)) return true;
    
        int temp[10];
        for(int s=0; s<n; s++){//这两重循环是用来枚举剪切的区间的长度
            for(int t=s+1; t<=n; t++){
                for(int pos=0; pos<s; pos++){//枚举区间要放入的位置,只要放到s之前就可以枚举所有的情况
                                            //别的地方也不符合实际情况啊,做的时候写成了pos<n,结果一直T
                    numSwap(temp, a, s, t, pos);
                        if(dfs(cur+1, maxd, temp))
                            return true;
                }
            }
        }
        return false;
    }
    
    int main(){
        //FRE();
        int kase = 0,a[10];
        while(scanf("%d",&n) && n){
            for(int i=0; i<n; i++){
                scanf("%d",&a[i]);
            }
    
            for(int i=0; i<=n; i++){
                if(dfs(0,i,a)){
                    printf("Case %d: %d
    ",++kase,i);
                    break;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/sykline/p/10321539.html
Copyright © 2011-2022 走看看