HihoCoder 1233 Boxes BFS

6 篇文章 0 订阅

https://hihocoder.com/problemset/problem/1233

题意:有很多个大小不同的盒子,排成一排,可以类似汉诺塔一样的移动他们,每次只能移动每个位置最顶上的那个盒子,只能移动到和他相邻的位置上去,并且是小盒子只能放在大盒子上面,问最后把这些盒子排成一个大小从小到大的顺序,需要的最少的次数,如果不可以,输出-1

想到是状态压缩从终点往回BFS预处理,但想歪了压缩的思路,想法是按位置所有的盒子状态压缩,这样会有很多种不会出现的状态,

看了题解就懂了,按每个盒子所在的位置压缩,n个盒子就一个n进制数,每一位的值代表现在这个盒子在哪个位置上,当然每个位置上最小的值必然就是最顶上的盒子

还有一点也是想歪了。。。。以为不同盒子数量是无差别的,只需要预处理出7个盒子时,对于小数量固定前某部分就可以,其实并不,多了一个盒子数量等于多了一个可移动的位置

#include<bits/stdc++.h>
using namespace std;
int ans[8][3000005],fac[10],a[10];
struct node
{
    int a,id;
}num[10];
int cmp(node u,node v)
{
    return u.a<v.a;
}
int main()
{
    memset(ans,-1,sizeof(ans));
    int n,now=1,state=0,i,j;
    //枚举有多少个盒子
    for(n=1;n<=7;n++)
    {
        fac[0]=1;
        for(i=1;i<n;i++)
        {
            fac[i]=fac[i-1]*n;
        }
        now=1,state=0;
        queue<int>Q;
        //终点状态值
        for(i=0;i<n;i++)
        {
            state+=now*i;
            now*=n;
        }
        ans[n][state]=0;
        Q.push(state);
        //BFS预处理所有可达状态的答案
        while(!Q.empty())
        {
            now=Q.front();
            Q.pop();
            for(i=0;i<n;i++)
            {
                a[i]=n;
            }

            state=now;
            for(i=0;i<n;i++)
            {
                int temp=state%n;
                if(a[temp]==n)
                    a[temp]=i;
                state/=n;
            }
            for(i=0;i<n;i++)
            {
                if(i!=0)
                {
                    if(a[i]<n&&a[i]<a[i-1])
                    {
                        state=now-fac[a[i]];
                        if(ans[n][state]==-1)
                        {
                            ans[n][state]=ans[n][now]+1;
                            Q.push(state);
                        }
                    }
                }
                if(i!=n-1)
                {
                    if(a[i]<n&&a[i]<a[i+1])
                    {
                        state=now+fac[a[i]];
                        if(ans[n][state]==-1)
                        {
                            ans[n][state]=ans[n][now]+1;
                            Q.push(state);
                        }
                    }
                }
            }
        }
    }


    int T;
    cin>>T;
    while(T--)
    {
        state=0;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&num[i].a);
            num[i].id=i;
        }
        sort(num,num+n,cmp);
        now=1;
        //压缩成状态值
        for(i=0;i<n;i++)
        {
            state+=now*num[i].id;
            now*=n;
        }
        printf("%d\n",ans[n][state]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值