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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值