题目大意:给你一个8*8的棋盘,上面有四个棋子,给你一个初始排布,一个目标排布,每次移动,可以把一个棋子移动到一个相邻的空位,或者跨过1个相邻的棋子,在保证棋子移动不超过8次的情况下,问能否把棋盘上的棋子由初始排布变成目标排布

8*8的棋盘,刚好不爆ull,状压那些位置有棋子

然后从初始状态开始,暴搜出当前状态下,移动一个棋子之后所有可能到达的状态

直接搜,总状态数是8^8,此外还有常数,会爆

由于给定了目标排布,考虑meet in middle

从起始状态和目标状态各搜4步即可

为了防止爆栈,同时为了好写好调,最好用bfs

具体实现呢,可以开两个队列正反同时bfs,搜到合法结果就break掉,可以减少很多常数

开2个map,表示正/反着跑能否到达状态s,如果能到达,则mp[s]=1

以正着搜为例,当前从que1中取出的状态为s,能到达的下一个状态为t,如果t出现在map1中,就不必在推入que1了,如果t出现在map2中,说明存在合法状态,break掉输出YES

代码好长啊..但在搜索题里算短的了

 #include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NN 5010
#define MM 2000
#define maxn 200
#define ll long long
#define uint unsigned int
#define ull unsigned long long
using namespace std; int id[][];
int xx[]={-,,,};
int yy[]={,,,-};
ull bin[];
int ax[],ay[],bx[],by[];
struct node{
ull s;int c;
friend bool operator < (const node &s1,const node &s2)
{return s1.s<s2.s;}
node(ull s,int c):s(s),c(c){}
node(){}
};
map<ull,int>mp[];
int check(int x,int y,ull s)
{
if(x<||y<||x>||y>)return ;
if(s&bin[id[x][y]]) return ;
return ;
} int main()
{
//freopen("t2.in","r",stdin);
for(int i=;i<=;i++)
for(int j=;j<=;j++)
id[i][j]=*(i-)+j-;
//px[id[i][j]]=i,py[id[i][j]]=j;
bin[]=;
for(int i=;i<=;i++)
bin[i]=bin[i-]<<;
while(scanf("%d%d%d%d",&ax[],&ay[],&ax[],&ay[])!=EOF)
{
scanf("%d%d%d%d",&ax[],&ay[],&ax[],&ay[]);
scanf("%d%d%d%d",&bx[],&by[],&bx[],&by[]);
scanf("%d%d%d%d",&bx[],&by[],&bx[],&by[]);
queue<node>q[];
ull s=,t=;
int cnt=,fx,fy,fl,nt;
for(int i=;i<=;i++)
s|=bin[id[ax[i]][ay[i]]];
mp[][s]=;
q[].push(node(s,));s=;
for(int i=;i<=;i++)
s|=bin[id[bx[i]][by[i]]];
mp[][s]=;
q[].push(node(s,));
int ans=,c,x,y;
while((!q[].empty()||!q[].empty())&&!ans)
{
if(!q[].empty())
{
node K=q[].front();q[].pop();
s=K.s,c=K.c;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
if(!(s&bin[id[i][j]])) continue;
for(int k=;k<;k++)
{
x=i+xx[k],y=j+yy[k];
fl=check(x,y,s);
if(!fl) continue;
if(fl==){
x+=xx[k],y+=yy[k];
if(check(x,y,s)!=) continue;
}
t=(s^bin[id[i][j]])|bin[id[x][y]];
if(mp[].find(t)!=mp[].end())
continue;
if(mp[].find(t)!=mp[].end())
{ans=;break;}
mp[][t]=;
if(c<) q[].push(node(t,c+));
if(ans==) break;
}
}
}
if(!q[].empty())
{
node K=q[].front();q[].pop();
s=K.s,c=K.c;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
if(!(s&bin[id[i][j]])) continue;
for(int k=;k<;k++)
{
x=i+xx[k],y=j+yy[k];
fl=check(x,y,s);
if(!fl) continue;
if(fl==){
x+=xx[k],y+=yy[k];
if(check(x,y,s)!=) continue;
}
t=(s^bin[id[i][j]])|bin[id[x][y]];
if(mp[].find(t)!=mp[].end())
continue;
if(mp[].find(t)!=mp[].end())
{ans=;break;}
mp[][t]=;
if(c<) q[].push(node(t,c+));
if(ans==) break;
}
}
}
}
if(ans==)
printf("YES\n");
else
printf("NO\n");
mp[].clear();
mp[].clear();
}
return ;
}

POJ 1198 / HDU 1401 Solitaire (记忆化搜索+meet in middle)的更多相关文章

  1. 不要62 hdu 2089 dfs记忆化搜索

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给你两个数作为一个闭区间的端点,求出该区间中不包含数字4和62的数的个数 思路: 数位dp中 ...

  2. poj 3249(bfs+dp或者记忆化搜索)

    题目链接:http://poj.org/problem?id=3249 思路:dp[i]表示到点i的最大收益,初始化为-inf,然后从入度为0点开始bfs就可以了,一开始一直TLE,然后优化了好久才4 ...

  3. poj 1661 Help Jimmy(记忆化搜索)

    题目链接:http://poj.org/problem?id=1661 一道还可以的记忆化搜索题,主要是要想到如何设dp,记忆化搜索是避免递归过程中的重复求值,所以要得到dp必须知道如何递归 由于这是 ...

  4. poj 1085 Triangle War 博弈论+记忆化搜索

    思路:总共有18条边,9个三角形. 极大极小化搜索+剪枝比较慢,所以用记忆化搜索!! 用state存放当前的加边后的状态,并判断是否构成三角形,找出最优解. 代码如下: #include<ios ...

  5. hdu 1078(dfs记忆化搜索)

    题意:容易理解... 思路:我开始是用dfs剪枝做的,968ms险过的,后来在网上学习了记忆化搜索=深搜形式+dp思想,时间复杂度大大降低,我个人理解,就是从某一个点出发,前面的点是由后面的点求出的, ...

  6. poj 1088 动态规划+dfs(记忆化搜索)

    滑雪 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   Description Mi ...

  7. poj 1579(动态规划初探之记忆化搜索)

    Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17843   Accepted: 9112 ...

  8. POJ 3616 Milking Time ——(记忆化搜索)

    第一眼看是线段交集问题,感觉不会= =.然后发现n是1000,那好像可以n^2建图再做.一想到这里,突然醒悟,直接记忆化搜索就好了啊..太蠢了.. 代码如下: #include <stdio.h ...

  9. POJ 1661 Help Jimmy ——(记忆化搜索)

    典型的记忆化搜索问题,dfs一遍即可.但是不知道WA在哪里了= =,一直都没找出错误.因为思路是很简单的,肯定是哪里写挫了,因此不再继续追究了. WA的代码如下,希望日后有一天能找出错误= =: —— ...

随机推荐

  1. Unity 脚本挂载位置

    原则:谁的脚本,挂载到谁身上 1,一般场景中会有个GameController脚本,挂在空物体上. 2,我见很多人脚本习惯挂到Camera上,好吧,不知算不算规范.

  2. day20 匿名函数,内置函数,面向过程编程

    目录 有名函数 匿名函数 max() min() sorted map filter 内置函数 面向过程编程 有名函数 def f1(): print('my name is f1') f1() my ...

  3. 多进程Socket_Client

    from socket import * #导入套接字模块的所有命令import struct #导入struck模块,用于封装数据流长度# from functools import partial ...

  4. 02操控奴隶——掌握它的语言“Python”

    一 编程常识 1编程语言的发展史 程序员是计算机的主人,主人与奴隶沟通的介质是编程语言,编程语言从诞生到现在它经历了那几个阶段呢? 2 语言的特性: 3 初期的编程语言更多的是站在计算机的角度去设计编 ...

  5. SQL中Group By的使用(转)

    1.概述 “Group By”从字面意义上理解就是根据“By”指定的规则对数据进行分组,所谓的分组就是将一个“数据集”划分成若干个“小区域”,然后针对若干个“小区域”进行数据处理. 2.原始表 3.简 ...

  6. C语言基本语法——数组

    一.一维数组 1.什么是数组 2.数组语法 3.下标 4.初始化 5.数组名和数组首地址 二.一维数组的应用 1.数组的赋值与拷贝 2.数组的正反遍历 3.随机数 4.数组乱序 5.数组的重复 三.二 ...

  7. BZOJ 2141 排队 (三维偏序CDQ+树状数组)

    题目大意:略 洛谷传送门 和 [CQOI2015]动态逆序对 这道题一样的思路 一开始的序列视为$n$次插入操作 把每次交换操作看成四次操作,删除$x$,删除$y$,加入$x$,加入$y$ 把每次操作 ...

  8. layui select change

    <select lay-filter="test"></select> layui.use([ 'form'], function() { var form ...

  9. 一行代码解决IE兼容性问题

    在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE给出了解决方案Google也给出了解决方案百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 <!Doctype html> ...

  10. 我一不小心把ubuntu里的ps这样的命令删掉了,应该怎么重装呢

    sudo apt-get --reinstall install procps