hiho 1233 Boxes(状态压缩+BFS)

题目大意:给n(n<8)个数放置在n个位置,小的数可以移动至大的数上面,反之不行。输出使得其有序最少需要的移动次数。


最多只有7个数,首先可以把输入的数离散化处理一下。

对于每一个数,考虑用三位二进制数来表示其位置。那么对于n个数,有2^(3*n)种状态。

假设a[i]的位置为pos[a[i]],可用pos[a[1]]*8^a[1]+pos[a[2]]*8^a[2]+pos[a[3]]*8^a[3]+……+pos[a[n]]*8^a[n]来表示每一个状态s。

如何根据当前状态确定某个数a[i]的位置?

设当前状态为s,则(s/(8^a[i]))%8即为当前状态下,数a[i]所在的位置pos[a[i]]。


设定了状态,并且知道了如何从某一状态下确定某个数的位置,就可以通过预处理,从目标位置开始bfs,得到每一个状态到达目标位置所需步数。然后O(1)回答每个询问了。

BFS时,枚举一个数,其可以向左或向右放置。由于放置时只能放在比它大的数上,因此可以去判断一下比它小的数是不是在要放置的位置上,如果在,则不放置。相当于一个剪枝。


#include<bits/stdc++.h>
using namespace std;
#define maxn 2100000
struct P{
    int x,id;
}p[7];

int ans[maxn];
bool vis[8];
queue<int> Q;

int getnum(int n)
{
    int s=0;
    for(int i=0;i<n;++i) s+=((i+1)*(1<<(3*i)));
    return s;
}

bool check(int a,int p,int s)
{
    for(int i=0;i<a;++i)
    {
        int pos=(s>>(3*i))%8;
        if(pos==p) return 0;
    }
    return 1;
}

void bfs(int n)
{
    int i,s=getnum(n);
    ans[s]=0;
    Q.push(s);
    while(!Q.empty())
    {
        s=Q.front();Q.pop();
        memset(vis,0,sizeof(vis));
        for(i=0;i<n;++i)
        {
            int pos=(s>>(3*i))%8;
            if(vis[pos]) continue;
            vis[pos]=1;
            if(pos>1&&!vis[pos-1]&&check(i,pos-1,s)){
                int tem=s-(1<<(3*i));
                if(ans[tem]==-1)
                {
                    Q.push(tem);
                    ans[tem]=ans[s]+1;
                }
            }
            if(pos<n&&!vis[pos+1]&&check(i,pos+1,s))
            {
                int tem=s+(1<<(3*i));
                if(ans[tem]==-1)
                {
                    Q.push(tem);
                    ans[tem]=ans[s]+1;
                }
            }
        }
    }
}

bool cmp1(P a,P b) {return a.x<b.x;}
bool cmp2(P a,P b) {return a.id<b.id;}

int main()
{
    int T,i,n;
    memset(ans,-1,sizeof(ans));
    for(i=1;i<=7;++i) bfs(i);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0;i<n;++i) {scanf("%d",&p[i].x);p[i].id=i;}
        sort(p,p+n,cmp1);
        for(i=0;i<n;++i) p[i].x=i;
        sort(p,p+n,cmp2);
        int s=0;
        for(i=0;i<n;++i) s+=((i+1)*(1<<(3*p[i].x)));
        printf("%d\n",ans[s]);
    }
    return 0;
}


你可能感兴趣的:(hiho 1233 Boxes(状态压缩+BFS))