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;
}
posted @ 2023-01-12 12:21  PKU_IMCOMING  阅读(4)  评论(0)    收藏  举报