洛谷2324骑士精神

在这里插入图片描述

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

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

输入输出样例
输入样例#1:
2
10110 10110 10110
01 ∗ 11 01*11 0111
10111 10111 10111
01001 01001 01001
00000 00000 00000
01011 01011 01011
110 ∗ 1 110*1 1101
01110 01110 01110
01010 01010 01010
00100 00100 00100
输出样例#1:
7
-1

在这里插入图片描述

这道题是cdcq出的考试题qwq,刚看到这道题的时候除了普通搜索还真没想到其他的算法(因为没见过QAQ)
可能考试的时候比较懵打了一个贼复杂的dfs…
还没调出来-.-
下午就知道是IDA*0.0
这道题中,由于步数限制给的很明确,所以迭代加深还是能比较明显的看出来的,
但就算是迭代加深这1s的时间也不够用,而且还没有啥好的剪枝。
于是我们可能就会感叹:要是代码跟我脑子一样自我判断就好了0.0
然后就出现了搜索中的估价函数
估价函数就类似于模拟自己在决策时影响自己判断的因素,首先要证明这些因素满足条件时一定能得到正确答案,然后把他们写成函数以影响自己的搜索(emm这么说会不会有点抽象)
就是把自己手推样例时所想的判断方法写在程序里。
然后在判断是否继续搜索时加上这个条件

这道题很容易想到我们自己在判断时是尽量把不合法的棋子往合法的地方移动
因此就用当前状态与目标状态不匹配的格子作为估价函数
判断条件就用当前步数+不匹配格数
且因为当估价函数为零时的状态一定是目标状态,所以这个策略一定是合法的。

然后就是看了才能懂我刚才在说什么的代码

#include<bits/stdc++.h>

using namespace std;

int goal[5][5] = {{1, 1, 1, 1, 1}, {0, 1, 1, 1, 1,}, {0, 0, 2, 1, 1}, {0, 0, 0, 0, 1}, {0, 0, 0, 0, 0}};

int mp[5][5], t, pd;
int dx[8] = {1, -1, 2, -2, 1, -1, 2, -2};
int dy[8] = {2, 2, -1, -1, -2, -2, 1, 1};

int tx, ty;

int g(){
	int ret = 0;
	for(int i = 0; i < 5; ++i)
		for(int j = 0; j < 5; ++j)
			if(mp[i][j] != goal[i][j]) ++ret;
	return ret;
}

bool IDA(int maxd, int d, int x, int y){
	if(!g()) return 1;
	if(g() + d - 1 > maxd) return 0;
	for(int i = 0; i < 8; ++i){
		int x1 = x + dx[i], y1 = y + dy[i];
		if(x1 < 0 || x1 > 4 || y1 < 0 || y1 > 4) continue;
		swap(mp[x1][y1], mp[x][y]);
		if(IDA(maxd, d + 1, x1, y1)) return 1;
		swap(mp[x1][y1], mp[x][y]); 
	}
	return 0;
}
int main()
{
	scanf("%d", &t);
	while(t--){
		pd = 0;
		for(int i = 0; i < 5; ++i){
			char s[5]; scanf("%s", s);
			for(int j = 0; j < 5; ++j){
				if(s[j] - '0' == 0) mp[i][j] = 0;
				else if(s[j] - '0' == 1) mp[i][j] = 1;
				else mp[i][j] = 2, tx = i, ty = j;
			}
		}
		for(int i = 1; i <= 15; ++i)
			if(IDA(i, 0, tx, ty)){
				pd = i; break;
			}
		if(pd) printf("%d\n", pd);
		else puts("-1");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBIGPPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值