其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了。

具体看代码(冗长):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <list>
#define rep(i,m,n) for(int i=m;i<=n;++i)
#define dop(i,m,n) for(int i=m;i>=n;--i)
#define lowbit(x) (x&(-x))
#define ll long long
#define INF 2147483647
#define re register
#define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define Close fclose(stdin);fclose(stdout);
#define pause system("pause");
using namespace std;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
char a[6][6];
struct Node{
int x[2], y[2], s, time, who; //x,y数组记录2个空点的位置,s表示当前的状态(二进制),who表示到谁走了
}start, begin, now, tmp;
int getHash(){ //棋盘转二进制状态
int ans = 0;
rep(i, 1, 4) rep(j, 1, 4) if(a[i][j] == 'B') ans |= (1 << ( ((i - 1) << 2) + j - 1) );
return ans;
}
queue <Node> q;
bool Win(Node x){ //判赢函数
int s = x.s;
//判断有没有黑点四子连棋
if( s&1&&s&(1<<4)&&s&(1<<8)&&s&(1<<12) || s&(1<<1)&&s&(1<<5)&&s&(1<<9)&&s&(1<<13)
|| s&(1<<2)&&s&(1<<6)&&s&(1<<10)&&s&(1<<14) || s&(1<<3)&&s&(1<<7)&&s&(1<<11)&&s&(1<<15)
|| s&1&&s&(1<<1)&&s&(1<<2)&&s&(1<<3) || s&(1<<4)&&s&(1<<5)&&s&(1<<6)&&s&(1<<7)
|| s&(1<<8)&&s&(1<<9)&&s&(1<<10)&&s&(1<<11) || s&(1<<12)&&s&(1<<13)&&s&(1<<14)&&s&(1<<15)
|| s&1&&s&(1<<5)&&s&(1<<10)&&s&(1<<15) || s&(1<<3)&&s&(1<<6)&&s&(1<<9)&&s&(1<<12))
return true;
//把空点的位置赋值为1
s|=1<<(((x.x[0]-1)<<2)+x.y[0]-1); s|=1<<(((x.x[1]-1)<<2)+x.y[1]-1);
//rep(i, 1, 4){ rep(j, 1, 4) printf("%d ", (s>>(((i-1)<<2)+j-1))&1); printf("\n"); }
//判断白点有没有四子连棋
if( (s^1)&1&&(s^(1<<4))&(1<<4)&&(s^(1<<8))&(1<<8)&&(s^(1<<12))&(1<<12) || (s^(1<<1))&(1<<1)&&(s^(1<<5))&(1<<5)&&(s^(1<<9))&(1<<9)&&(s^(1<<13))&(1<<13)
|| (s^(1<<2))&(1<<2)&&(s^(1<<6))&(1<<6)&&(s^(1<<10))&(1<<10)&&(s^(1<<14))&(1<<14) || (s^(1<<3))&(1<<3)&&(s^(1<<7))&(1<<7)&&(s^(1<<11))&(1<<11)&&(s^(1<<15))&(1<<15)
|| (s^1)&&(s^(1<<1))&(1<<1)&&(s^(1<<2))&(1<<2)&&(s^(1<<3))&(1<<3) || (s^(1<<4))&(1<<4)&&(s^(1<<5))&(1<<5)&&(s^(1<<6))&(1<<6)&&(s^(1<<7))&(1<<7)
|| (s^(1<<8))&(1<<8)&&(s^(1<<9))&(1<<9)&&(s^(1<<10))&(1<<10)&&(s^(1<<11))&(1<<11) || (s^(1<<12))&(1<<12)&&(s^(1<<13))&(1<<13)&&(s^(1<<14))&(1<<14)&&(s^(1<<15))&(1<<15)
|| (s^1)&(1)&&(s^(1<<5))&(1<<5)&&(s^(1<<10))&(1<<10)&&(s^(1<<15))&(1<<15) || (s^(1<<3))&(1<<3)&&(s^(1<<6))&(1<<6)&&(s^(1<<9))&(1<<9)&&(s^(1<<12))&(1<<12))
return true;
return false;
}
int l[] = { 233, -1, 1, 0, 0 }, r[] = { 666, 0, 0, -1, 1 }, id, X, Y, kong, v[20000010];
int getHash(Node x){ //不要hack我
return x.s + x.x[0] * 10007 + x.x[1] * 107 + x.y[1] * 677 + x.y[0] * 97;
}
int main(){
rep(i, 1, 4)
rep(j, 1, 4){
cin>>a[i][j];
if(a[i][j] == 'O') //记录空点位置
if(!start.x[0]) start.x[0] = i, start.y[0] = j;
else start.x[1] = i, start.y[1] = j;
}
start.s = getHash();
start.time = 0;
begin = start;
start.who = 0;
begin.who = 1;
q.push(start);
q.push(begin);
v[getHash(begin)] = v[getHash(start)] = 1;
while(!q.empty()){ //bfs
Node now = q.front();
q.pop();
rep(i, 0, 1){
rep(j, 1, 4){
X = now.x[i] + l[j]; Y = now.y[i] + r[j];
if(X <= 0 || X > 4 || Y <= 0 || Y > 4 || X == now.x[i^1] && Y == now.y[i^1]) continue; //不能出界,也不能走到另外一个空点
id = ((X - 1) << 2) + Y - 1;
kong = ((now.x[i] - 1) << 2) + now.y[i] - 1;
if(((now.s >> id) & 1) == now.who){ //如果是到这个棋走
tmp = now;
tmp.s &= ~(1 << id); //交换
tmp.s |= tmp.who << kong; //位置
tmp.x[i] = X;
tmp.y[i] = Y;
if(v[getHash(tmp)]) continue;
v[getHash(tmp)] = 1;
tmp.time++;
tmp.who^=1;
if(Win(tmp)){
printf("%d\n", tmp.time);
return 0;
}
q.push(tmp);
}
}
}
}
return 0;
}

【洛谷 P2346】四子连棋(状态压缩,搜索)的更多相关文章

  1. 洛谷P2346四子连棋

    题目描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步. 黑白双方交替走棋,任意一方可 ...

  2. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

  3. Codevs 四子连棋 (迭代加深搜索)

    题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双 ...

  4. 洛谷 P2704 [NOI2001]炮兵阵地 (状态压缩DP+优化)

    题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...

  5. 洛谷 P1896 [SCOI2005]互不侵犯 (状态压缩DP)

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...

  6. 洛谷 P2622 关灯问题II (状态压缩+BFS)

    题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...

  7. 【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋

    一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的( ...

  8. codevs1004四子连棋[BFS 哈希]

    1004 四子连棋   时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold   题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...

  9. Codevs p1004 四子连棋

                          四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向 ...

随机推荐

  1. Python-学习-项目1-即时标记-1

    买了一本Python入门,奈何看不下去,只能是先看后面的项目,看到那里不懂的时候在回去学习. 项目名字:即时标记 大致的意思就是把一个纯文本文件标记成自己想要的格式文件. 首先就是待处理文本,我找不到 ...

  2. 阿里云DTS VS MySQLdump

    云平台的到来,使得越来越多用户的数据库由云下迁到云上.对于这种情况,阿里对此提出两种方案,一种是MySQL自带的MySQLdump,另外一种就是阿里云的DTS. DTS支持异构数据源之间的数据迁移同步 ...

  3. GraphSAGE 代码解析(一) - unsupervised_train.py

    原创文章-转载请注明出处哦.其他部分内容参见以下链接- GraphSAGE 代码解析(二) - layers.py GraphSAGE 代码解析(三) - aggregators.py GraphSA ...

  4. 九度OJ--Q1163

    import java.util.ArrayList;import java.util.Scanner; /* * 题目描述: * 输入一个整数n(2<=n<=10000),要求输出所有从 ...

  5. z 变换

    1. z 变换 单位脉冲响应为 \(h[n]\) 的离散时间线性时不变系统对复指数输入 \(z^n\) 的响应 \(y[n]\) 为 \[ \tag{1} y[n] = H(z) z^{n}\] 式中 ...

  6. TensorFlow 同时调用多个预训练好的模型

    在某些任务中,我们需要针对不同的情况训练多个不同的神经网络模型,这时候,在测试阶段,我们就需要调用多个预训练好的模型分别来进行预测. 调用单个预训练好的模型请点击此处 弄明白了如何调用单个模型,其实调 ...

  7. URAL 1736 Chinese Hockey(网络最大流)

    Description Sergey and Denis closely followed the Chinese Football Championship, which has just come ...

  8. python基础之列表解析

    python列表解析:是一个让人欣喜的术语,你可以在一行使用一个for循环将所有的值放在一个列表之中.python列表解析属于python的迭代中的一种,相比python for循环速度会快很多. e ...

  9. 16常用API

    常用API 今日内容介绍 u 正则表达式 u Date u DateFormat u Calendar 第1章 正则表达式 1.1 正则表达式的概念 正则表达式(英语:Regular Expressi ...

  10. FileReader 获取图片BASE64 代码 并预览

    FileReader 获取图片的base64 代码 并预览 FileReader ,老实说我也不怎么熟悉.在这里只是记录使用方法. 方法名 参数 描述 abort none 中断读取 readAsBi ...