题目:LINK
题意: 在一个8×8的棋盘中,给定你4个棋子A,再给你4个棋子B,问你在8步之内能不能够从A位置移动到B位置;
规则:棋子能能上下左右移动,同时能跳过相邻的棋子到达相邻棋子的空地方;
如果直接搜索无论是bfs还是dfs都会TLE的,可以发现无论是从开始的棋盘搜索到最终的棋盘,还是从最终的棋盘搜索到开始的棋盘是一样的。
所以我们从开始的棋盘搜索4步,从最终的棋盘搜索4步,检测有没有相同的可以达到的状态。
我是用DFS写的,分别从初始态和最终态搜索,复杂度2*(16^4) ,为了记录是否可以到达某个棋盘,可以状态压缩4个点的坐标,一个8个数字,每个数字大小1~8(占3位),一共用24位.
当然也可以用BFS写。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
int mm[9][9];
bool vis[1<<24];
int flag ;
const int n = 8,m = 8;
struct node
{
pair<int, int > p[6];
};
int dir[4][2]= { 0, 1, 0, -1, 1, 0, -1, 0};
node S, T;
pair<int, int> test(pair<int, int> in, int adx, int ady)
{
pair<int, int> ret;
int nx = in.first + adx;
int ny = in.second + ady;
if(nx < 1 || nx > n || ny < 1 || ny > m) {
ret.first = ret.second = -1;
return ret;
}
if(mm[nx][ny] != 1) {
ret.first = nx; ret.second = ny;
return ret;
}
nx += adx;
ny += ady;
if(nx < 1 || nx > n || ny < 1 || ny > m) {
ret.first = -1; ret.second = -1;
return ret;
}
if(mm[nx][ny] != 1) {
ret.first = nx; ret.second = ny;
return ret;
}
ret.first = ret.second = -1;
return ret;
}
int getsta(node in)
{
int sta = 0;
int xx , yy;
for(int i = 1; i<=4; i++) {
xx = in.p[i].first;
yy = in.p[i].second;
xx --; yy --;
sta = (sta << 3) | xx;
sta = (sta << 3) | yy;
}
return sta;
}
void dfs(int x, node now, int ff)
{
if(flag) return ;
node next = now;
sort(next.p+1, next.p+5);
int sta = getsta(next);
if(!ff) vis[sta] = 1;
else if(vis[sta]) {
flag = 1; return ;
}
if(x > 4) return ;
memset(mm, 0, sizeof(mm));
for(int i=1; i<=4; i++) mm[now.p[i].first][now.p[i].second] = 1;
for(int i=1; i<=4; i++) {
for(int j = 0; j< 4; j++) {
next = now;
pair<int, int> tmp = test(now.p[i], dir[j][0], dir[j][1]);
if(tmp.first == -1) continue;
next.p[i] = tmp;
dfs(x+1, next, ff);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int tmp;
while(scanf("%d", &tmp) != EOF) {
S.p[1].first = tmp;
scanf("%d", &S.p[1].second);
for(int i=2; i<=4; i++) scanf("%d%d", &S.p[i].first, &S.p[i].second);
for(int i=1; i<=4; i++) scanf("%d%d", &T.p[i].first, &T.p[i].second);
memset(vis, 0,sizeof(vis));
sort(S.p+1, S.p+1+4);
sort(T.p+1, T.p+1+4);
flag = 0;
dfs(1, S, 0);
dfs(1, T, 1);
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}