HDU 1401 Solitaire(双向搜索)

2024-05-29 07:32
文章标签 搜索 双向 hdu 1401 solitaire

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

题目: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_JUDGEfreopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGEint 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;
}


这篇关于HDU 1401 Solitaire(双向搜索)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

csu1329(双向链表)

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

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

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 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

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

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,所以直接一

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while