题目大意:给你一个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 三维软件单位导入资源单位比例

    三维软件 内部米制尺寸/m 默认设置导入unity中的尺寸/m 与unity单位比例 Maya 1 100 1:100 3DS MAX 1 0.01 100:1 Cinema 4D 1 100 1:1 ...

  2. Windows下安装XAMPP,Wordpress

    配置XAMPP:   1.下载:https://www.apachefriends.org/zh_cn/download.html(下载速度日了狗!)  2.安装XAMPP;  3.启动apache, ...

  3. 作用域与this

    面向对象 一.单例模式 1.1 对象数据类型的作用: 把描述一个对象的属性和方法放在一个单独的空间,与其他的对象分割开,即时出现属性名相同的情况,也不会产生冲突 var name="xiao ...

  4. [读书笔记] Python数据分析 (五) pandas入门

    pandas: 基于Numpy构建的数据分析库 pandas数据结构:Series, DataFrame Series: 带有数据标签的类一维数组对象(也可看成字典) values, index 缺失 ...

  5. UDP Linux编程(客户端&服务器端)

    服务器端 服务器不用绑定地址,他只需要进行绑定相应的监听端口即可. #include <sys/types.h> #include <sys/socket.h> #includ ...

  6. java实现随机数的生成

    一,课程中的动手动脑的问题 1,编写一个方法,使用以上算法生成指定数目的随机整数. public void suiJiShu(){ Scanner input=new Scanner(System.i ...

  7. URL中一些特殊符号的替代符

    下表中列出了一些URL特殊符号及编码 十六进制值 1.+ URL 中+号表示空格 %2B 2.空格 URL中的空格可以用+号或者编码 %20 3./ 分隔目录和子目录 %2F 4.? 分隔实际的 UR ...

  8. DDL表结构修改

      *1)创建表    create table 表名(     字段名 类型,     ....    );     //以现有表复制一个新表   create table j012 as   se ...

  9. 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage

    P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...

  10. JavaScript正則表達式知识汇总

    Js 正則表達式知识汇总 正則表達式: 1.什么是RegExp?RegExp是正則表達式的缩写.RegExp 对象用于规定在文本中检索的内容. 2.定义RegExp:var +变量名=new RegE ...