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]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】