隐藏页面特效

2449 骑士精神

2449 骑士精神

 

2005年省队选拔赛四川

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

     在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。

        给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘:

                         

为了体现出骑士精神,他们必须以最少的步数完成任务。

输入描述 Input Description

第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

输出描述 Output Description

对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

样例输入 Sample Input
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
样例输出 Sample Output

7

-1

数据范围及提示 Data Size & Hint

见题面

分类标签 Tags 点此展开 

 
 
解题思路:骑士的跳动实质上是空格的跳动,搜索同时判断是否与目标状态一致,记录一下步数。
 
IDA*
时间:玄学
#include<iostream> using namespace std; const char goal[5][6]={{"11111"},{"01111"},{"00*11"},{"00001"},{"00000"}}; const int dx[]={1,2,2,1,-1,-2,-2,-1}; const int dy[]={2,1,-1,-2,-2,-1,1,2}; char s[5][6];int T,ans;bool flag; inline int deal(){//估价函数(A*的标志) int res=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(s[i][j]!=goal[i][j]) res++; return res; } void dfs(int now,int x,int y,int limit){ int c=deal(); if(now==limit){if(!c) ans=limit,flag=1;return ;}//同层的ans是一样的 if(now-1+c>limit) return ;//c个不同的至少需要c-1操作,超过限制,剪枝 for(int i=0;i<8;i++){ int nx=x+dx[i],ny=y+dy[i]; if(nx>=0&&nx<5&&ny>=0&&ny<5){ swap(s[x][y],s[nx][ny]); if(flag) return ;//已有答案,迅速跳出 dfs(now+1,nx,ny,limit); swap(s[x][y],s[nx][ny]); } } } int main(){ cin>>T; while(T--){ int x,y; ans=16; for(int i=0;i<5;i++) for(int j=0;j<5;j++){ cin>>s[i][j]; if(s[i][j]=='*') x=i,y=j;//空格点 } for(int k=0;k<=15;k++){//枚举限制层数 flag=0;ans=16; dfs(0,x,y,k); if(ans==k)break;//前面有答案,后面就不更新了 } cout<<(ans==16?-1:ans)<<endl;//判一下是否超过15步 } return 0; }

 

A*算法

时间:玄学

#include<iostream>//朴素A*,没有上面的剪枝部分,当然跑的不如上面的快,但是便于理解 #include<cstring> using namespace std; const char goal[5][6]={{"11111"},{"01111"},{"00*11"},{"00001"},{"00000"}}; const int dx[]={1,2,2,1,-1,-2,-2,-1}; const int dy[]={2,1,-1,-2,-2,-1,1,2}; char s[5][6];int T,ans; inline bool same(){ return !memcmp(s,goal,sizeof s); } inline int deal(int dep){ for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(s[i][j]!=goal[i][j]) dep++; return dep; } void dfs(int dep){ if(same()) ans=min(ans,dep-1); if(dep>=ans) return ; int x,y; for(int i=0;i<5;i++) for(int j=0;j<5;j++) if(s[i][j]=='*') x=i,y=j; for(int i=0;i<8;i++){ x+=dx[i];y+=dy[i]; if(x>=0&&x<5&&y>=0&&y<5){ swap(s[x][y],s[x-dx[i]][y-dy[i]]); if(deal(dep)<=ans) dfs(dep+1); swap(s[x][y],s[x-dx[i]][y-dy[i]]); } x-=dx[i];y-=dy[i]; } } int main(){ cin>>T; while(T--){ ans=16; for(int i=0;i<5;i++) for(int j=0;j<5;j++) cin>>s[i][j]; dfs(1); cout<<(ans==16?-1:ans)<<endl; } return 0; }

 

 


__EOF__

本文作者shenben
本文链接https://www.cnblogs.com/shenben/p/5717059.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   神犇(shenben)  阅读(327)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示