1 条题解
-
0
自动搬运
来自洛谷,原作者为

YellowBean_Elsa
You find me waiting in the wings......搬运于
2025-08-24 21:26:46,当前版本为作者最后更新于2020-02-16 12:01:31,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我觉得这题应该蓝。。。
首先看数据范围可知,这题就是个普通搜索。
然后按照题意,很快写出了一个简单的暴搜。
当然,加上了最显而易见的剪枝:如果当前答案已大于搜索已经得到的最小值,直接 return;
然而这样T飞了。。。
然后我们注意到,题目还有一个限制条件:每个格子必须且仅能经过一次
那么,如果在某一个状态时,我们可以判断此时已经不可能按要求走完魔法阵,则可以直接 return;
knock the blackboard!!!
经过画图,我们找到了一种这样的状态:
当我们走到一个位置时,如果已经走过它的上下,却没有走过它左右的任意一格,或者相反,已经走过它的左右,却没有走过它上下的任意一格,那么一定无法走完魔法阵,直接 return;

证明:如图,从A走到B的路径隔绝了C和D,因此不可能在不经过A到B路径的情况下同时走到C和D,证毕。
加上这个可行性剪枝后,就AC了。
//coder: Feliks-GMYB #include<bits/stdc++.h> using namespace std; int n,m,k1,k2,ans=(1<<30); bool vis[55][55]; int col[30][2]; inline int read(){ int x=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return x; }void dfs(int x,int y,int p,int mx){ //可行性剪枝 if(vis[x-1][y]&&vis[x+1][y]&&!vis[x][y+1]&&!vis[x][y-1])return; if(!vis[x-1][y]&&!vis[x+1][y]&&vis[x][y+1]&&vis[x][y-1])return; if(mx>ans)return;//显而易见的最优性剪枝 //按照公式要求进行操作 if(p<=((n*m)>>1)){ col[p][0]=x; col[p][1]=y; }else mx=max(mx,abs(col[p-n*m/2][0]-x)*k1+abs(col[p-n*m/2][1]-y)*k2); if(p==n*m){//done the maze if(mx<ans)ans=mx; return; }//尝试向四面走 if(!vis[x-1][y]){ vis[x-1][y]=1; dfs(x-1,y,p+1,mx); vis[x-1][y]=0; }//up if(!vis[x+1][y]){ vis[x+1][y]=1; dfs(x+1,y,p+1,mx); vis[x+1][y]=0; }//down if(!vis[x][y-1]){ vis[x][y-1]=1; dfs(x,y-1,p+1,mx); vis[x][y-1]=0; }//left if(!vis[x][y+1]){ vis[x][y+1]=1; dfs(x,y+1,p+1,mx); vis[x][y+1]=0; }//right }int main(){ n=read(),m=read(),k1=read(),k2=read(); //常见搜索防越界操作: //地图四周初始时赋为已走过,防止搜索时走出地图 for(int i=0;i<=n+1;i++) vis[i][0]=vis[i][m+1]=1; for(int i=0;i<=m+1;i++) vis[0][i]=vis[n+1][i]=1; vis[1][1]=1;dfs(1,1,1,0); printf("%d\n",ans); return 0; }多嘴一句,这种可行性剪枝对于所有要求一笔画方格图的搜索都适用,也可看作一种实用技巧
- 1
信息
- ID
- 578
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者