把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【BZOJ2954】[POI2002] 超级马(暴搜)

点此看题面

大致题意: 给定一匹马的\(n\)种跳动方式,询问它是否能跳到无限棋盘上的所有点。

前言

现在越来越菜了,这种\(SB\)题还要想半天。

发现最近做题总是会莫名其妙走到死胡同里,就好比这题,一开始想歪了就一发不可收拾,最后还是因为知道这是\(SB\)题才会想出该怎么做。

一些能写的剪枝最后都懒得写了(而且一看好像大家都在写\(BFS\)就我写了个\(DFS\)果然DFS才是我的真爱),成功成为了黑暗爆炸OJ上跑的最慢的代码。

暴搜

考虑一匹马能跳到所有点,就说明它通过若干步向四个方向分别都能跳动一个点。

马单次跳动步长是\(-100\sim 100\),假设我们令马从\((100,100)\)开始跳,那么就让它在\(200\times 200\)的棋盘上一直跳跳跳,跳到跳过的点直接\(return\)

然后最后判断是否跳到过\((99,100),(101,100),(100,99),(100,101)\)这四个点即可。

显然这一过程可以加一堆剪枝,例如找到答案立刻退出、优先搜可能得到更优策略的情况等等,反正它又不卡我,也就都懒得去写了。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200
using namespace std;
int n,dx[N+5],dy[N+5],vis[N+5][N+5];
I void dfs(CI x,CI y,CI ti)//暴搜
{
	if(x<0||x>200||y<0||y>200||vis[x][y]==ti) return;vis[x][y]=ti;//越界或已搜过就不再搜
	for(RI i=1;i<=n;++i) dfs(x+dx[i],y+dy[i],ti);//枚举方向跳动
}
int main()
{
	RI Tt,T,i;for(scanf("%d",&Tt),T=1;T<=Tt;++T)
	{
		for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",dx+i,dy+i);dfs(100,100,T),
		puts(vis[99][100]==T&&vis[101][100]==T&&vis[100][99]==T&&vis[100][101]==T?"TAK":"NIE");//判断是否能向四个方向跳动一步
	}return 0;
}
posted @ 2020-05-20 08:05  TheLostWeak  阅读(196)  评论(0编辑  收藏  举报