洛谷P4289 移动玩具 HAOI2008 搜索+状压

正解:状压

解题报告:

先,放下传送门QwQ

说真的我jio得这题不管是思路还是实现上,都还是有一定难度的?然后就看到神仙hl博客里一句"太水了不讲了"就过掉了,,,好的趴太强辽QAQ

但是这题我开始是真的没想到状压,,,知道状压之后实现代码实现了好久,,,看来灵巧是真的菜趴QAQ

然后就讲下这题QwQ

首先这题,一眼bfs板子题嘛,大体的框架应该都还是想得出来的

但是如果!你和sd灵巧想到了一个路子上!直接存的矩阵!你就可以获得10pts的好成绩,,,显然会MLE的啊喂!

然后就考虑,它不是只有01嘛,显然状压鸭!

然后照理来说就做完了

然而sd灵巧代码实现能力太差了,,,打了俩小时死活调不出来,,,就放弃了,拿的hl的代码改了下过的(但改动挺大的我jio得,比他代码好看多了2333333

然后另外注意一下还用了俩优化(不过似乎不用也能A?

一个是双向搜索,通过beg和tail实现的

另一个是显然的一个结论,就是对于俩俩交换你只用搜和左边交换和上边交换,和右和下的显然会被别的格子枚举到,就可以/2了(也没快多少的说QAQ

没了,放下代码就跑了!

#include<bits/stdc++.h>
using namespace std;
#define rg register
#define ll int
#define mp make_pair
#define rp(i,x,y) for(rg ll i=x;i<=y;++i)
#define my(i,x,y) for(rg ll i=x;i>=y;--i)
const ll N=70000;
ll beg[N],tail[N],ans,temp[5][5],dx[]={0,1,0},dy[]={0,0,1},t1;
queue< ll > q;

inline void frhash(int x){my(i,4,1)my(j,4,1){temp[i][j]=x&1;x>>=1;}}
inline int tohash(){int ret=0;rp(i,1,4)rp(j,1,4){ret<<=1;ret|=temp[i][j];}return ret;}
inline bool jde(int x,int y){return x<5 && y<5 && x>0 && y>0;}
inline int bfs(void)
{
    while(!q.empty())
    {
        int now=q.front(),tp=0;frhash(now);q.pop();
        rp(i,1,4)
            rp(j,1,4)
                rp(k,1,2)
                    if(jde(i+dx[k],j+dy[k]))
                    {
                        swap(temp[i][j],temp[i+dx[k]][j+dy[k]]);tp=tohash();
                        if(beg[tp] && tail[tp])return beg[tp]+tail[tp]-2;
                        if(beg[now] && (!beg[tp]))beg[tp]=beg[now]+1,q.push(tp);
                        if(tail[now] && (!tail[tp]))tail[tp]=tail[now]+1,q.push(tp);
                        swap(temp[i][j],temp[i+dx[k]][j+dy[k]]);
                    }
    }
}

int main()
{
    rp(t,1,4)rp(i,1,4)scanf("%1d",&temp[t][i]);t1=tohash();beg[t1]=1;q.push(t1);
    rp(t,1,4)rp(i,1,4)scanf("%1d",&temp[t][i]);t1=tohash();tail[t1]=1;q.push(t1);
    cout<<bfs()<<endl;
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/10307447.html