今天两道题都没AC出来 不过还是学到很多东西的
先放一下错误代码 :
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int start[8];
int goal[8];
struct node {
int checkedboard[8];
int foot = 0;
};
bool check(int x, int y, int arr[]) {
if (x >= 0 && x < 8 && y >= 0 && y < 8) {
for (int i = 0; i < 4; i++) {
if (arr[2 * i] == x && arr[2 * i + 1] == y) return false;
}
return true;
}
return false;
}
int dir[4][2] = {
{1, 0},
{-1, 0},
{0, 1},
{0, -1}
};
vector<int> get_sorted_state(int arr[]) {
vector<pair<int, int>> coords;
for (int i = 0; i < 4; i++) {
coords.push_back({ arr[2 * i], arr[2 * i + 1] });
}
sort(coords.begin(), coords.end());
vector<int> sorted_state;
for (const auto& p : coords) {
sorted_state.push_back(p.first);
sorted_state.push_back(p.second);
}
return sorted_state;
}
bool bfs() {
node start_node, goal_node;
memcpy(start_node.checkedboard, start, sizeof(start_node.checkedboard));
memcpy(goal_node.checkedboard, goal, sizeof(goal_node.checkedboard));
queue<node> q_start, q_goal;
q_start.push(start_node);
q_goal.push(goal_node);
set<vector<int>> visited_start, visited_goal;
visited_start.insert(get_sorted_state(start_node.checkedboard));
visited_goal.insert(get_sorted_state(goal_node.checkedboard));
while (!q_start.empty() && !q_goal.empty()) {
if (q_start.size() > q_goal.size()) {
swap(q_start, q_goal);
swap(visited_start, visited_goal);
}
int size = q_start.size();
for (int i = 0; i < size; i++) {
node n = q_start.front();
q_start.pop();
vector<int> current_state = get_sorted_state(n.checkedboard);
if (visited_goal.find(current_state) != visited_goal.end()) {
return true;
}
if (n.foot > 8) continue;
for (int i = 0; i < 4; i++) {
int x = n.checkedboard[2 * i];
int y = n.checkedboard[2 * i + 1];
for (int j = 0; j < 4; j++) {
node new_node;
memcpy(&new_node, &n, sizeof(struct node));
new_node.foot++;
int newx = x + dir[j][0];
int newy = y + dir[j][1];
if (check(newx, newy, n.checkedboard)) {
new_node.checkedboard[2 * i] = newx;
new_node.checkedboard[2 * i + 1] = newy;
vector<int> new_state = get_sorted_state(new_node.checkedboard);
if (visited_start.find(new_state) == visited_start.end()) {
visited_start.insert(new_state);
q_start.push(new_node);
}
}
else {
int jumpx = newx + dir[j][0];
int jumpy = newy + dir[j][1];
if (check(jumpx, jumpy, n.checkedboard)) {
new_node.checkedboard[2 * i] = jumpx;
new_node.checkedboard[2 * i + 1] = jumpy;
vector<int> new_state = get_sorted_state(new_node.checkedboard);
if (visited_start.find(new_state) == visited_start.end()) {
visited_start.insert(new_state);
q_start.push(new_node);
}
}
}
}
}
}
}
return false;
}
int main() {
while (cin >> start[0]) {
for (int i = 1; i < 8; i++)
cin >> start[i];
for (int i = 0; i < 8; i++)
cin >> goal[i];
if (bfs()) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
return 0;
}
关键点:
使用双向广搜:降低时间复杂度 一个搜索4步即可 因为5 3 可以转换为4 4 不缺情况
使用sort排序:否则visited会有大量重复状态
四个点四个方向注意判断是否可以跳
使用八维数组记录坐标
下面是大神的代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define eps 1e-9
#define P system("pause")
using namespace std;
struct point {
int x,y;
friend bool operator<(point a,point b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
};
struct node
{
point s[4]; //记录四个棋子的位置
int step;
};
char hash[8][8][8][8][8][8][8][8]; //如果是1则q1中的节点经过了,2则q2中的节点经过了,0表示为经过
queue<node> q1,q2;
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
void setflag(node a,char k)
{
hash[a.s[0].x][a.s[0].y][a.s[1].x][a.s[1].y][a.s[2].x][a.s[2].y][a.s[3].x][a.s[3].y]=k;
}
char getflag(node a)
{
return hash[a.s[0].x][a.s[0].y][a.s[1].x][a.s[1].y][a.s[2].x][a.s[2].y][a.s[3].x][a.s[3].y];
}
bool judge(node &t,int i,int j,int m) //这个写的很巧妙,自己也写了个,总是wa,最后还是跟着答案写了
{
if( m==1 )
{
if( t.step >=4 )//最多移动4步
return false;
t.step ++;
}
t.s[i].x += d[j][0];
t.s[i].y += d[j][1];
if( t.s[i].x >= 0 && t.s[i].x < 8 && t.s[i].y >=0 && t.s[i].y<8 )
{ int k;
for(k=0; k<4 ; k++)
{
if(i!=k)
{
if( t.s[i].x==t.s[k].x&&t.s[i].y==t.s[k].y )
if(m == 1) return judge(t, i , j , 2);
else return false;
}
}
if( k>=4 )
{
sort( t.s , t.s + 4 );
return true;
}
}
return false;
}
bool dbfs()
{
int i,j;
char k;
node u;
while(!q1.empty()||!q2.empty())
{
if(!q1.empty())
{
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
u=q1.front();
if(judge(u,i,j,1)){
k=getflag(u);
if(k==2) return 1;
else if(k==0){
sort(u.s,u.s+4);
setflag(u,1);
q1.push(u);
}
}
}
q1.pop();
}
if(!q2.empty())
{
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
u=q2.front();
if(judge(u,i,j,1)){ //判断可行,主要求u
k=getflag(u);
if(k==1) return 1;
else if(k==0) {
sort(u.s,u.s+4);
setflag(u,2);
q2.push(u);
}
}
}
q2.pop();
}
}
return 0;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);cc
int i,j;
node A,B;
while(scanf("%d%d",&i,&j)!=EOF)
{
memset(hash,0,sizeof(hash));
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
i--;j--;
A.s[0].x=i; A.s[0].y=j;
for(i=1;i<4;i++){
scanf("%d%d",&A.s[i].x,&A.s[i].y);
A.s[i].x--;A.s[i].y--;
}
sort(A.s,A.s+4);
setflag(A,1);
for(i=0;i<4;i++){
scanf("%d%d",&B.s[i].x,&B.s[i].y);
B.s[i].x--;B.s[i].y--;
}
sort(B.s,B.s+4);
setflag(B,2);
A.step=B.step=0;
q1.push(A);
q2.push(B);
if(dbfs()) printf("YES\n");
else printf("NO\n");
}
// P;
return 0;
}
这个judge函数写的实在是太好了 真的简单明了:
大概意思为我有 1正常状态 2跳跃状态
当我为1 检查是否超出步数 return false 然后更新node查看是否越界 再分两种情况有重合和无重合在正常状态有就变跳跃 没就继续 跳跃状态没有就true 有就false 最后排序;