双向广搜——POJ 1198

2024-09-05 04:32
文章标签 poj 1198 双向

本文主要是介绍双向广搜——POJ 1198,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对应POJ题目:点击打开链接


Solitaire
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 3777 Accepted: 1345
Case Time Limit: 1000MS

Description

Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right respectively. 

There are four identical pieces on the board. In one move it is allowed to: 

  • move a piece to an empty neighboring field (up, down, left or right), 
  • jump over one neighboring piece to an empty field (up, down, left or right). 


There are 4 moves allowed for each piece in the configuration shown above. As an example let's consider a piece placed in the row 4, column 4. It can be moved one row up, two rows down, one column left or two columns right. 
Write a program that: 

  • reads two chessboard configurations from the standard input, 
  • verifies whether the second one is reachable from the first one in at most 8 moves, 
  • writes the result to the standard output. 

Input

Each of two input lines contains 8 integers a1, a2, ..., a8 separated by single spaces and describes one configuration of pieces on the chessboard. Integers a2j-1 and a2j (1 <= j <= 4) describe the position of one piece -- the row number and the column number respectively.

Output

The output should contain one word YES if a configuration described in the second input line is reachable from the configuration described in the first input line in at most 8 moves, or one word NO otherwise.

Sample Input

4 4 4 5 5 4 6 5
2 4 3 3 3 6 4 6

Sample Output

YES


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN=1000;
const int INF=1<<30;
typedef long long LL;
int go[4][2]={0,1,0,-1,1,0,-1,0};
set<LL>s0;
set<LL>s1;struct point
{int x[4],y[4],step;
}pb,pe;LL Get(point pt)
{LL h=0;for(int i=0; i<4; i++){h|=(1LL<<(pt.x[i]*8+pt.y[i]-1));}return h;
}bool cal(point pt, int u)
{for(int i=0; i<4; i++){if(i!=u && pt.x[i]==pt.x[u] && pt.y[i]==pt.y[u])return 1;}return 0;
}bool tex(int x,int y)
{if(x<0 || x>=8 || y<0 || y>=8) return 0;return 1;
}void bfs(point p, bool flag)
{queue<point>q;p.step=0;if(!flag) s0.insert(Get(p));else s1.insert(Get(p));q.push(p);point p1;while(!q.empty()){p=q.front();q.pop();if(p.step==4) continue;for(int i=0; i<4; i++){for(int j=0; j<4; j++){p1=p;p1.x[i]+=go[j][0];p1.y[i]+=go[j][1];p1.step++;if(!flag){if(tex(p1.x[i],p1.y[i]) && !s0.count(Get(p1))){if(!cal(p1,i)){s0.insert(Get(p1));q.push(p1);}else{p1.x[i]+=go[j][0];p1.y[i]+=go[j][1];if(tex(p1.x[i],p1.y[i]) && !s0.count(Get(p1)) && !cal(p1,i)){s0.insert(Get(p1));q.push(p1);}}}}else{if(tex(p1.x[i],p1.y[i]) && !s1.count(Get(p1))){if(!cal(p1,i)){LL h=Get(p1);if(s0.find(h)!=s0.end()){printf("YES\n"); return;}s1.insert(h);q.push(p1);}else{p1.x[i]+=go[j][0];p1.y[i]+=go[j][1];if(tex(p1.x[i],p1.y[i]) && !s1.count(Get(p1) && !cal(p1,i))){LL h=Get(p1);if(s0.find(h)!=s0.end()){printf("YES\n"); return;}s1.insert(h);q.push(p1);}}}}}}}if(flag) printf("NO\n");
}int main()
{//freopen("in.txt","r",stdin);int x,y;while(scanf("%d%d", &x,&y)==2){--x;--y;pb.x[0]=x; pb.y[0]=y;int i;for(i=1; i<4; i++) {scanf("%d%d", &x, &y);--x;--y;pb.x[i]=x; pb.y[i]=y;}for(i=0; i<4; i++) {scanf("%d%d", &x, &y);--x;--y;pe.x[i]=x; pe.y[i]=y;}if(Get(pb)==Get(pe)) {printf("YES\n"); continue;}bfs(pb, 0);bfs(pe, 1);s0.erase(s0.begin(), s0.end());s1.erase(s1.begin(), s1.end());}
}



这篇关于双向广搜——POJ 1198的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1137955

相关文章

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

poj 1511 Invitation Cards(spfa最短路)

题意是给你点与点之间的距离,求来回到点1的最短路中的边权和。 因为边很大,不能用原来的dijkstra什么的,所以用spfa来做。并且注意要用long long int 来存储。 稍微改了一下学长的模板。 stack stl 实现代码: #include<stdio.h>#include<stack>using namespace std;const int M

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

poj 1502 MPI Maelstrom(单源最短路dijkstra)

题目真是长得头疼,好多生词,给跪。 没啥好说的,英语大水逼。 借助字典尝试翻译了一下,水逼直译求不喷 Description: BIT他们的超级计算机最近交货了。(定语秀了一堆词汇那就省略吧再见) Valentine McKee的研究顾问Jack Swigert,要她来测试一下这个系统。 Valentine告诉Swigert:“因为阿波罗是一个分布式共享内存的机器,所以它的内存访问

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一