P4289 [HAOI2008] 移动玩具

题目链接:https://www.luogu.com.cn/problem/P4289
状压+bfs

将初始状态和目标状态都保存下来,然后对于每个有棋子的位置 直接上下左右bfs即可。

2024.4.30 upd :代码添加了注释


const int maxn = 2e5+10;
queue<int> que;
int ed,st,dis[maxn];
int ans=0;
char s[10];
int main()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));
    int n=4;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=4;j++)
        {
            st|=(s[j]-'0')*(1<<((i-1)*4+j));//把起点的关键点信息存下来
        }
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=4;j++)
        {
            ed|=(s[j]-'0')*(1<<((i-1)*4+j));//把终点的关键点信息存下来
        }
    }
    dis[st]=0;
    que.push(st);
    //bfs dis[x]  x代表当前棋盘上的状态,dis[x]代表从起始状态到目标状态最少需要移动多少步
    while(!que.empty())
    {
        int x=que.front();
        que.pop();
        if(x==ed)
        {
            break;
        }
        //一共16格 压16位
        for(int i=1;i<=16;i++)
        {
            if(x&(1<<i))//如果说当前点是1
            {
                if(i+4<=16&&!(x&(1<<(i+4)))&&dis[(x^(1<<i))|1<<(i+4)]>dis[x]+1)
                {//向下移动 并且目标点(下面那个点)是0 并且当前移动之后达到目标状态的代价更小
                    dis[(x^(1<<i))|1<<(i+4)]=dis[x]+1;
                    que.push((x^(1<<i))|1<<(i+4));
                    //(x^(1<<i)|1<<(i+4)) 改变后的棋盘状态,当前位移动到下面那么当前位的位置就要置零
                    //然后下面一位原本是0,现在要置1,然后状压更新状态
                }
                if(i-4>=1&&!(x&(1<<(i-4)))&&dis[(x^(1<<i))|1<<(i-4)]>dis[x]+1)
                {//向上
                    dis[(x^(1<<i))|1<<(i-4)]=dis[x]+1;
                    que.push((x^(1<<i))|1<<(i-4));
                }
                if(i%4!=0&&!(x&(1<<(i+1)))&&dis[(x^(1<<i))|1<<(i+1)]>dis[x]+1)
                {//向右 不能超过右边界
                    dis[(x^(1<<i))|1<<(i+1)]=dis[x]+1;
                    que.push((x^(1<<i))|1<<(i+1));
                }
                if(i%4!=1&&!(x&(1<<(i-1)))&&dis[(x^(1<<i))|1<<(i-1)]>dis[x]+1)
                {//向左 不能超过左边界
                    dis[(x^(1<<i))|1<<(i-1)]=dis[x]+1;
                    que.push((x^(1<<i))|1<<(i-1));
                }
            }
        }
    }
    printf("%d\n",dis[ed]);
}
posted @ 2024-04-18 10:43  Captainfly19  阅读(11)  评论(0编辑  收藏  举报