HDU 3900 状压BFS

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <cmath>
#define LL long long
#define print(k) cout<<#k"="<<k<<endl;
using namespace std;
struct State
{
    LL state,step;
};

struct Block
{
    LL l,c;
    bool t;
}block[20];
LL n,red;

inline LL getr(LL x,LL k)
{
    return (x&(7LL<<k*3))>>k*3;
}

inline bool check(LL x,LL k1,LL k2)
{
    if(getr(x,k1)>=getr(x,k2)) swap(k1,k2);
    if(block[k1].t==block[k2].t)
    {
        if(block[k1].c!=block[k2].c) return true;
        if(getr(x,k1)+block[k1].l>getr(x,k2)) return false;
        else return true;
    }
    if(getr(x,k1)<=block[k2].c && getr(x,k1)+block[k1].l>block[k2].c &&
       getr(x,k2)<=block[k1].c && getr(x,k2)+block[k2].l>block[k1].c) return false;
    else return true;
}

inline bool check(LL x)
{
    LL i,j;
    for(i=0;i<n;i++)
    {
        if(getr(x,i)+block[i].l>6)
        {
            return false;
        }
        for(j=0;j<i;j++)
        {
            if(!check(x,i,j))
            {
                return false;
            }
        }
    }
    return true;
}

inline bool done(LL x)
{
    if(getr(x,red)+block[red].l==6) return true;
    return false;
}

int main()
{
    //freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    while(cin>>n)
    {
        LL i,j,k;
        LL lx,ly,rx,ry;
        State head,tail;
        tail.state=0;
        for(i=0;i<n;i++)
        {
            cin>>k>>lx>>ly>>rx>>ry;
            if(lx==rx)
            {
                block[i].t=0;
                block[i].l=abs(ly-ry)+1;
                block[i].c=lx;
                tail.state+=min(ly,ry)<<3*k;
            }
            else if(ly==ry)
            {
                block[i].t=1;
                block[i].l=abs(lx-rx)+1;
                block[i].c=ly;
                tail.state+=min(lx,rx)<<3*k;
            }
            else exit(-1);
        }
        cin>>red;
        set<LL> st;st.clear();
        st.insert(tail.state);
        queue<State> q;
        tail.step=0;
        q.push(tail);
        LL ans=-1;
        while(q.size() && ans<0)
        {
            head=q.front();
            ///if(getr(head.state,red)==0) print(getr(head.state,red));
            if(done(head.state))
            {
                ans=head.step;
                break;
            }
            for(i=0;i<n && ans<0;i++)
            {
                LL m=getr(head.state,i);
                for(k=1;k+m+block[i].l<=6 && ans<0 && check(head.state+k*(1LL<<3*i));k++) if(st.count(head.state+k*(1LL<<3*i))==0)
                {
                    //print(m) print(k)
                    tail.state=head.state+k*(1LL<<3*i);
                    tail.step=head.step+1;
                    q.push(tail);
                    st.insert(tail.state);
                    if(done(tail.state))
                    {
                        ans=tail.step;
                        break;
                    }
                }
                for(k=1;m-k>=0 && ans<0 && check(head.state-k*(1LL<<3*i));k++) if(st.count(head.state-k*(1LL<<3*i))==0)
                {
                    tail.state=head.state-k*(1LL<<3*i);
                    tail.step=head.step+1;
                    q.push(tail);
                    st.insert(tail.state);
                    if(done(tail.state))
                    {
                        ans=tail.step;
                        break;
                    }
                }
            }
            q.pop();
        }
        cout<<max(ans,1LL)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值