2015网络赛北京赛区G题(bfs+预处理)

本文通过深度优先搜索(DFS)预处理方法,解决给定不同大小的盒子,通过左右移动达到从小到大有序排列所需的最少移动次数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题意:给n个不同大小的盒子,小盒子可以叠在大盒子上,每次可向左或右相邻的位置移动该位置最顶的盒子,求使所有盒子从小到大有序所需最少移动次数。

思路:从终态bfs爆搜预处理出到达所有状态需要的步数。

#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
//#include <conio.h>
#include <iostream>
using namespace std;
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define ll long long int
#define maxn 205
#define mod 1000000007
#define pii pair<int,int>

int v7[8][8][8][8][8][8][8];
int v6[8][8][8][8][8][8];
int v5[8][8][8][8][8];
int v4[8][8][8][8];
int v3[8][8][8];
int v2[8][8];
bool check(int a[],int n,int step){
    if(n==2){
        if(v2[a[1]][a[2]]!=-1) return 0;
        else {
            v2[a[1]][a[2]]=step;return 1;
        }
    }
    else if(n==3){
        if(v3[a[1]][a[2]][a[3]]!=-1) return 0;
        else {
            v3[a[1]][a[2]][a[3]]=step;return 1;
        }
    }
    else if(n==4){
        if(v4[a[1]][a[2]][a[3]][a[4]]!=-1) return 0;
        else {
            v4[a[1]][a[2]][a[3]][a[4]]=step;return 1;
        }
    }
    else if(n==5){
        if(v5[a[1]][a[2]][a[3]][a[4]][a[5]]!=-1) return 0;
        else {
            v5[a[1]][a[2]][a[3]][a[4]][a[5]]=step;return 1;
        }
    }
    else if(n==6){
        if(v6[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]]!=-1) return 0;
        else {
            v6[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]]=step;return 1;
        }
    }
    else if(n==7){
        if(v7[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]]!=-1) return 0;
        else {
            v7[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]]=step;return 1;
        }
    }
}
struct node{
    int a[10];
    int step;
};
void solve(int n){
    int a[10];
    for(int i=1;i<=n;i++) a[i]=i;
    check(a,n,0);
    queue<node> qq;
    node s;s.step=0;
    for(int i=1;i<=n;i++) s.a[i]=i;
    qq.push(s);
    while(!qq.empty()){
        s=qq.front();qq.pop();
        for(int i=1;i<=n;i++){//第i个点向左或右移
           // int kk=s.a[i];
            int l=1;
            int r=1;
            for(int j=1;j<i;j++){
                if(s.a[j]==s.a[i]-1) l=0;//左有更小的
                if(s.a[j]==s.a[i]+1) r=0;//右有更小的
                if(s.a[j]==s.a[i]) l=r=0;//该点上方有更小的
            }
            if(s.a[i]-1<1) l=0;
            if(s.a[i]+1>n) r=0;
            if(l){
                s.a[i]=s.a[i]-1;s.step+=1;
                if(check(s.a,n,s.step)) qq.push(s);
                s.a[i]+=1;s.step-=1;
            }
            if(r){
                s.a[i]+=1;s.step+=1;
                if(check(s.a,n,s.step)) qq.push(s);
                s.a[i]-=1;s.step-=1;
            }
        }
    }
}
void init(){
    memset(v7,-1,sizeof(v7));
    memset(v6,-1,sizeof(v6));
    memset(v5,-1,sizeof(v5));
    memset(v4,-1,sizeof(v4));
    memset(v3,-1,sizeof(v3));
    memset(v2,-1,sizeof(v2));
    for(int i=2;i<=7;i++){
        solve(i);
    }
}
int h[10005],t,n,a[10],b[10];
int main()
{
    rd(t);
    init();
    while(t--){
        rd(n);
        for(int i=1;i<=n;i++){
            rd(b[i]);h[b[i]]=i;
        }
        sort(b+1,b+1+n);
        for(int i=1;i<=n;i++) a[i]=h[b[i]];
        if(n==1) printf("0\n");
        else if(n==2) printf("%d\n",v2[a[1]][a[2]]);
        else if(n==3) printf("%d\n",v3[a[1]][a[2]][a[3]]);
        else if(n==4) printf("%d\n",v4[a[1]][a[2]][a[3]][a[4]]);
        else if(n==5) printf("%d\n",v5[a[1]][a[2]][a[3]][a[4]][a[5]]);
        else if(n==6) printf("%d\n",v6[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]]);
        else if(n==7) printf("%d\n",v7[a[1]][a[2]][a[3]][a[4]][a[5]][a[6]][a[7]]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值