P2324
[SCOI2005]骑士精神
题目描述

输入格式
第一行有一个正整数 \(T\)(\(T \le 10\)),表示一共有 \(T\) 组数据。
接下来有 \(T\) 个 \(5 \times 5\) 的矩阵,0 表示白色骑士,1 表示黑色骑士,* 表示空位。两组数据之间没有空行。
输出格式
对于每组数据都输出一行。如果能在 \(15\) 步以内(包括 \(15\) 步)到达目标状态,则输出步数,否则输出 -1。
样例 #1
样例输入 #1
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
样例输出 #1
7
-1
提示

迭代加深搜索 IDA* 我不会!!!
拿到这道题肯定先想的是BFS 于是学习到了针对BFS的优化 A*算法
设置一个估价函数 这题的估价函数就是当前状态与目标状态不同的个数
这样now_step+cal>15直接continue就可以了!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int T;
char m[6][6];
int dp[8]={-11,-9,-7,-3,+3,+7,+9,+11};
int flag=0,tim;
string start,target;
struct did{
int c;
string now;
}z,d;
inline int cal(string s)
{
int cnt=0;
for(int i=1;i<=25;i++)
if(s[i]!=target[i])
cnt++;
return cnt;
}
void bfs()
{
queue<did>q;
set<string>st;
z.c=0,z.now=start;
if(start==target)
{
cout<<0<<"\n";
flag=1;
return ;
}
q.push(z);st.insert(start);
while(!q.empty())
{
tim++;
// if(tim>1e4)return ;
// cout<<tim<<" ";
z=q.front();
q.pop();
string s=z.now;
if(z.c>15){flag=0;return ;}
if(s==target){flag=1;cout<<z.c<<"\n";return ;}
if(z.c+cal(s)>15)continue;
int pos;
for(int i=1;i<=25;i++)
if(s[i]=='*')
{
pos=i;
break;
}
int xx,yy;
if(pos>=1&&pos<=5)xx=1;
else if(pos>=6&&pos<=10)xx=2;
else if(pos>=11&&pos<=15)xx=3;
else if(pos>=16&&pos<=20)xx=4;
else xx=5;
yy=pos-(xx-1)*5;
for(int i=0;i<8;i++)
{
int npos=pos+dp[i];
if(npos<1||npos>25)continue;
int x,y;
if(npos>=1&&npos<=5)x=1;
else if(npos>=6&&npos<=10)x=2;
else if(npos>=11&&npos<=15)x=3;
else if(npos>=16&&npos<=20)x=4;
else x=5;
y=npos-(x-1)*5;
if((x-xx)*(x-xx)+(y-yy)*(y-yy)!=5)continue;
string t=s;
swap(t[pos],t[npos]);
if(!st.count(t))
{
d.c=z.c+1;
d.now=t;
q.push(d);
st.insert(t);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
target=" 111110111100*110000100000";
cin>>T;
while(T--)
{
tim=0;
flag=0;
start=" ";
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
cin>>m[i][j],start+=m[i][j];
bfs();
if(!flag)cout<<-1<<"\n";
}
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号