SCOI 2005 骑士精神 && FZU 骑士 搜索+剪枝

lydsy 1085 题目链接:点击打开链接

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int dx[] = {1, 1, -1, -1, 2, 2, -2, -2};
const int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
const int N = 8;
const int mx = (1<<25)-1;
const int M = 30;

int stpos, st, edpos, ed, zz;
char s[N][N];
int r[M], c[M], id[N][N];
bool f;

void dfs(int cur, int g, int pos, int mxdep) {
	if (f)
		return ;
	if (cur == mxdep) {
		if (g == ed && pos == edpos)
			f = 1;
	} else {
		if (__builtin_popcount(g&zz)*2 > mxdep-cur)
			return ;
		int curx = r[pos], cury = c[pos], nx, ny, ng;
		for (int i = 0; i < 8; ++i) {
			nx = curx+dx[i];
			ny = cury+dy[i];
			if (nx>=0&&nx<5&&ny>=0&&ny<5) {
				ng = g;
				if (ng>>id[nx][ny]&1) {
					ng |= 1<<pos;
					ng ^= 1<<id[nx][ny];
				}
				dfs(cur+1, ng, id[nx][ny], mxdep);
			}
		}
	}
}
void work() {
	st = 0;
	for (int i = 0; i < 5; ++i) {
		scanf("%s", s[i]);
		for (int j = 0; j < 5; ++j) {
			if (s[i][j] == '1')
				st |= 1 << id[i][j];
			if (s[i][j] == '*')
				stpos = id[i][j];
		}
	}
	f = 0;
	for (int i = 0; i <= 15; ++i) {
		dfs(0, st, stpos, i);
		if (f) {
			printf("%d\n", i);
			return ;
		}
	}
	puts("-1");
}
void prepare() {
	int tot = 0;
	for (int i = 0; i < 5; ++i)
		for (int j = 0; j < 5; ++j) {
			id[i][j] = tot;
			r[tot] = i;
			c[tot++] = j;
		}
	ed = 0;
	edpos = 12;
	ed |= 1<<0; ed |= 1<<1; ed |= 1<<2; ed |= 1<<3; ed |= 1<<4;
	ed |= 1<<6; ed |= 1<<7; ed |= 1<<8; ed |= 1<<9;
	ed |= 1<<13; ed |= 1<<14;
	ed |= 1<<19;
	//
	zz = 0;
	zz |= 1<<5;
	zz |= 1<<10; zz |= 1<<11;
	zz |= 1<<15; zz |= 1<<16; zz |= 1<<17; zz |= 1<<18;
	zz |= 1<<20; zz |= 1<<21; zz |= 1<<22; zz |= 1<<23; zz |= 1<<24;
}
int main() {
	prepare();
	int cas; scanf("%d", &cas);
	while (cas--)
		work();
	return 0;
}

FZU:

#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int dx[] = {1, 1, -1, -1, 2, 2, -2, -2};
const int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
const int N = 8;
const int mx = (1<<25)-1;
const int M = 30;

int stpos, st, edpos, ed, zz;
char s[N][N];
int r[M], c[M], id[N][N];
bool f;

void dfs(int cur, int g, int pos, int mxdep) {
	if (f)
		return ;
	if (cur == mxdep) {
		if (g == ed && pos == edpos)
			f = 1;
	} else {
		if (__builtin_popcount(g&zz)*2 > mxdep-cur)
			return ;
		int curx = r[pos], cury = c[pos], nx, ny, ng;
		for (int i = 0; i < 8; ++i) {
			nx = curx+dx[i];
			ny = cury+dy[i];
			if (nx>=0&&nx<5&&ny>=0&&ny<5) {
				ng = g;
				if (ng>>id[nx][ny]&1) {
					ng |= 1<<pos;
					ng ^= 1<<id[nx][ny];
				}
				dfs(cur+1, ng, id[nx][ny], mxdep);
			}
		}
	}
}
void work() {
	st = 0;
	for (int i = 0; i < 5; ++i) {
		scanf("%s", s[i]);
		for (int j = 0; j < 5; ++j) {
			if (s[i][j] == '1')
				st |= 1 << id[i][j];
			if (s[i][j] == '*')
				stpos = id[i][j];
		}
	}
	f = 0;
	for (int i = 0; i <= 15; ++i) {
		dfs(0, st, stpos, i);
		if (f) {
			printf("%d\n", i);
			return ;
		}
	}
	puts("Bored!");
}
void prepare() {
	int tot = 0;
	for (int i = 0; i < 5; ++i)
		for (int j = 0; j < 5; ++j) {
			id[i][j] = tot;
			r[tot] = i;
			c[tot++] = j;
		}
	ed = 0;
	edpos = 12;
	ed |= 1<<0; ed |= 1<<1; ed |= 1<<2; ed |= 1<<3; ed |= 1<<4;
	ed |= 1<<6; ed |= 1<<7; ed |= 1<<8; ed |= 1<<9;
	ed |= 1<<13; ed |= 1<<14;
	ed |= 1<<19;
	//
	zz = 0;
	zz |= 1<<5;
	zz |= 1<<10; zz |= 1<<11;
	zz |= 1<<15; zz |= 1<<16; zz |= 1<<17; zz |= 1<<18;
	zz |= 1<<20; zz |= 1<<21; zz |= 1<<22; zz |= 1<<23; zz |= 1<<24;
}
int main() {
	prepare();
	int cas; scanf("%d", &cas);
	while (cas--)
		work();
	return 0;
}
时间: 2024-10-20 08:01:25

SCOI 2005 骑士精神 && FZU 骑士 搜索+剪枝的相关文章

BZOJ 1085 SCOI 2005 骑士精神 IDA*

题目大意:有一张5*5的棋盘,上面有12和黑棋还有12个白棋.问最少多步可以到达目标状态. 思路:搜索+剪枝.至于剪枝我就用ID+A*的组合了,因为都不难想,估价函数就是当前图和目标图有多少个方块不一样.如果当前步数+估价大于当前迭代加深的层数就退出. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std;

【BZOJ1085】【SCOI2005】骑士精神 [A*搜索]

骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位. 在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. Input

算法复习——迭代加深搜索(骑士精神bzoj1085)

题目: Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. Input 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位.两组数据

A*算法详解 BZOJ 1085骑士精神

转载1:A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算法. 启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无畏的搜索路径,提到了效率.在启发式搜索中,对位置的估价是十分重要的.采用了不同的估价可以有不同的效果. 估价函数:从当前节点移动到目标节点的预估费用:这个估计

【日常学习】【IDA*】codevs2449 骑士精神题解

题目描述 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. 输入描述 Input Description 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,

[BZOJ]1085 骑士精神(SCOI2005)

这种鲜明的玄学风格很明显就是十几年前的题目. Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. Input 第一行有一个正整数T,表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑

BZOJ1085:[SCOI2005]骑士精神——题解+IDA*粗略讲解

http://www.lydsy.com/JudgeOnline/problem.php?id=1085 Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务. Input 第一行有一个正整数T(T<=10)

埃及分数&amp;&amp;The Rotation Game&amp;&amp;骑士精神——IDA*

IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题. 估价函数设计思路:观察一步最多能向答案靠近多少. 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系列互不相同的单位分数(形如:1/a,即分子为1),要求:分解成的单位分数数量越少越好,如果数量一样,最小的那个单位分数越大越好. 如: 19/45 = 1/3 + 1/12 + 1/180; 19/45 = 1/5 + 1/6 + 1/18; 以上两种分解方法都要3个单位分数,但下面一个的最小单位分

bzoj1085 [SCOI2005]骑士精神

1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2490  Solved: 1422[Submit][Status][Discuss] Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上. 给定一个初始的棋盘,怎样才能经过移动