zoukankan      html  css  js  c++  java
  • 北京网络赛G BOXES 大模拟+BFS

    题目描述

    Description

    There is a strange storehouse in PKU. In this storehouse there are n slots for boxes, forming a line. In each slot you can pile up any amount of boxes. The limitation is that you can only pile a smaller one above a bigger one, in order to keep balance. The slots are numbered from 1 to n. The leftmost one is slot 1.

    At first there is exactly one box in each slot. The volume of the box in slot i is vi. As a virgo, you decide to sort these boxes by moving some of them. In each move you can choose a slot and move the top box in this slot to an adjacent slot (of course you can only put it on the top). You should ensure that the limitation mentioned above is still satisfied after this move. After the sort operation, there should be exactly one box in each slot, and for each pair of adjacent slots, the box in the left one should be smaller than the box in the right one.

    Your task is to calculate the minimum number of moves you need to sort the boxes.

    Input

    In the first line there’s an integer T(T≤6000), indicating the number of test cases. The following 2T lines describe the test cases.

    In each test case, the first line contains an integer n, indicating the number of slots. The second line contains n integers v1,v2…vn, indicating the volume of the boxes. It is guaranteed that all vi in a test case are different.

    Please note that n<8,0≤vi≤104

    Output

    For each test case, print a line containing one integer indicating the answer. If it’s impossible to sort the boxes, print -1.

    Sample Input
    4
    3
    2 1 3
    2
    7 8
    2
    10000 1000
    3
    97 96 95
    Sample Output
    4
    0
    -1
    20

    #include <bits/stdc++.h>
    using namespace std;
    int vis1[7];
    int vis2[7][7];
    int vis3[7][7][7];
    int vis4[7][7][7][7];
    int vis5[7][7][7][7][7];
    int vis6[7][7][7][7][7][7];
    int vis7[7][7][7][7][7][7][7];
    struct node{
        int a[7];
        int step;
    };
    map<int,int> Hash;
    int a[10],b[10],c[10];
    bool check(int a[],int num,int step){ 
        if(num==1){
            if(vis1[a[0]]>=0) return true;
            else{vis1[a[0]]=step;return false;}
        }
        if(num==2){
            if(vis2[a[0]][a[1]]>=0) return true;
            else {vis2[a[0]][a[1]]=step;return false;}
        }
        if(num==3){
            if(vis3[a[0]][a[1]][a[2]]>=0) return true;
            else {vis3[a[0]][a[1]][a[2]]=step;return false;}
        }
        if(num==4){
            if(vis4[a[0]][a[1]][a[2]][a[3]]>=0) return true;
            else {vis4[a[0]][a[1]][a[2]][a[3]]=step;return false;}
        }
        if(num==5){
            if(vis5[a[0]][a[1]][a[2]][a[3]][a[4]]>=0) return true;
            else {vis5[a[0]][a[1]][a[2]][a[3]][a[4]]=step;return false;}
        }
        if(num==6){
            if(vis6[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]]>=0) return true;
            else {vis6[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]]=step;return false;}
        }
        if(num==7){
            if(vis7[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]]>=0) return true;
            else {vis7[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]]=step;return false;}
        }
        return false;
    }
    void init(){
        memset(vis1,-1,sizeof(vis1));
        memset(vis2,-1,sizeof(vis2));
        memset(vis3,-1,sizeof(vis3));
        memset(vis4,-1,sizeof(vis4));
        memset(vis5,-1,sizeof(vis5));
        memset(vis6,-1,sizeof(vis6));
        memset(vis7,-1,sizeof(vis7));
    }
    void bfs(int a[],int num){
        node k;k.step=0;
        for(int i=0;i<num;i++){k.a[i]=i;}
        check(a,num,0);
        queue<node> que;que.push(k);
        int b[7];
        while(!que.empty()){
            node top=que.front();que.pop();
            for(int i=0;i<num;++i)
                b[i]=top.a[i];
            for(int i=0;i<num;++i){
                int l=b[i]-1;
                int r=b[i]+1;
                if(l<0) l=-1;
                if(r>=num) r=-1;
                for(int j=0;j<i;++j) if(b[j]==b[i]){l=r=-1;}
                for(int j=0;j<i;++j) if(b[j]==b[i]-1) {l=-1;}
                for(int j=0;j<i;++j) if(b[j]==b[i]+1) {r=-1;}
                if(l!=-1){
                    int temp=b[i];
                    b[i]=l;
                    node s;
                    for(int j=0;j<num;++j) {s.a[j]=b[j];}
                    s.step=top.step+1;
                    if(!check(b,num,s.step)){
                        que.push(s);
                    }
                    b[i]=temp;
                }
                if(r!=-1){
                    int temp=b[i];
                    b[i]=r;
                    node s;
                    for(int j=0;j<num;++j) {s.a[j]=b[j];}
                    s.step=top.step+1;
                    if(!check(b,num,s.step)){
                        que.push(s);
                    }
                    b[i]=temp;
                }
            }
        }
    }
    
    int main(){
        int T,n;
        for(int i=0;i<7;i++){
            a[i]=i;
        }
        init();
        for(int i=1;i<=7;i++){
            bfs(a,i);
        }
        for(scanf("%d",&T);T;--T){
            scanf("%d",&n);Hash.clear();
            vector<int> Q;
            for(int i=0;i<n;i++){
                scanf("%d",b+i);
                Q.push_back(b[i]);
            }
            sort(Q.begin(),Q.end());
            for(int i=0;i<(int)Q.size();i++){
                Hash[Q[i]]=i;
            }
            for(int i=0;i<n;i++){
                c[Hash[b[i]]]=i;
            }
            if(n==1){
                if(c[0]==0){
                    printf("0
    ");
                }
                else printf("%d
    ",vis1[c[0]]);
            }
            if(n==2){
                if(c[0]==0&&c[1]==1){
                    printf("0
    ");
                }
                else printf("%d
    ",vis2[c[0]][c[1]]);
            }
            if(n==3){
                if(c[0]==0&&c[1]==1&&c[2]==2){
                    printf("0
    ");
                }
                else printf("%d
    ",vis3[c[0]][c[1]][c[2]]);
            }
            if(n==4){
                if(c[0]==0&&c[1]==1&&c[2]==2&&c[3]==3){
                    printf("0
    ");
                }
                else printf("%d
    ",vis4[c[0]][c[1]][c[2]][c[3]]);
            }
            if(n==5){
                if(c[0]==0&&c[1]==1&&c[2]==2&&c[3]==3&&c[4]==4){
                    printf("0
    ");
                }
                else printf("%d
    ",vis5[c[0]][c[1]][c[2]][c[3]][c[4]]);
            }
            if(n==6){
                if(c[0]==0&&c[1]==1&&c[2]==2&&c[3]==3&&c[4]==4&&c[5]==5){
                    printf("0
    ");
                }
                else printf("%d
    ",vis6[c[0]][c[1]][c[2]][c[3]][c[4]][c[5]]);
            }
            if(n==7){
                if(c[0]==0&&c[1]==1&&c[2]==2&&c[3]==3&&c[4]==4&&c[5]==5&&c[6]==6){
                    printf("0
    ");
                }
                else printf("%d
    ",vis7[c[0]][c[1]][c[2]][c[3]][c[4]][c[5]][c[6]]);
            }
        }
        return 0;
    }


    首先对之前搜到这个题解的人说声对不起,因为之前写的有问题也没修补

    好了我来解释一下代码的关键部分。。。

    好的,这其实是个sb题,没睡醒的同学可以看一下下面的解释。。。

    首先是状态定义

    a[i]:第i大的元素在值为a[i]的位置上

    然后,我们可以离线地做这道题

    初始状态有序让a[i]=i

    然后让他去搜索所有有效的状态,因为你正着搜结果和结果往乱了推其实值是一样的,这是一个可逆的过程

    然后我们使用bfs爆搜所有从有序状态出发的状态并且记录答案

    bfs中的关键判断是

    1,这个第i大的元素,上面有没有东西

    检查方法,遍历0~i-1大的元素,看一下这些元素里有没有和它在同一个位置

    2,相邻的右边的柱子能不能放东西

    检查方法,遍历0~i-1大的元素,看一下这些元素有没有放到a[i]+1这个槽里,只要有那么至少是不能放的,因为只可能更小

    3,相邻的左边的柱子能不能放东西

    检查方法,遍历0~i-1大的元素,看一下这些元素有没有放到a[i]-1这个槽里,只要有那么至少是不能放的,因为只可能更小

    然后就是复制状态,检查访问过没有,判断一下加入队列

    然后就是一些细节的东西

    数组下标什么的千万别搞混。。。离散化之后记得维护c[i]的意义,千万别直接扔个rank数组进去...

  • 相关阅读:
    《程序员代码面试指南》第三章 二叉树问题 先序、中序和后序数组两两结合重构二叉树
    《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题
    《程序员代码面试指南》第三章 二叉树问题 在二叉树中找到一个节点的后继节点
    《程序员代码面试指南》第三章 二叉树问题 通过有序数组生成搜索二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断一个树是搜索二叉树和完全二叉树
    《程序员代码面试指南》第三章 二叉树问题 根据后序数组重建搜素二叉树
    《程序员代码面试指南》第三章 二叉树问题 判断二叉树是否为搜素二叉树
    博弈知识入门引导
    ZZNUOJ-2157: 水滴来袭-【干扰阅读-卡模糊精度1e-8的问题】
    ZZNUOJ-2155-单身man集合-【标程做法:数位DP-1-10^8,提前暴力打表法: 砍时间复杂度到10^5】
  • 原文地址:https://www.cnblogs.com/linkzijun/p/5280903.html
Copyright © 2011-2022 走看看