其实这题可以直接二进制状压做,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. 《数据结构与算法分析:C语言描述》读书笔记

    我们数据结构的课用了这本英文教材,作者是Mark Allen Weiss.总体来说比<算法导论>简单很多,但内容上交集非常大.其实是因为去掉了大多数证明和数学,对于没有耐心看符号和公式的人 ...

  2. ubuntu 14.04安装nginx+php

    转自:http://www.cnblogs.com/helinfeng/p/4219051.html 基于最新的Ubuntu 14.04(2014年9月)搭建nginx.php.mysql环境,以下全 ...

  3. UIButton内部子控件自定义布局-“UIEdgeInsets”

    UIButton UIButton做frame动画时,不响应点击 在一个View内部加入几个按钮,然后改变这个view的frame来做动画,但是按钮不响应点击事件. 问题代码 __block CGRe ...

  4. linq里lambda写的join查询,并附加动态拼接的条件,条件为enum类型的查询

    因为查询条件不固定的原因,sql式的linq查询没法动态拼接条件. 网上搜的资料整理之后终于解决. 参考资料: enum使用 http://blog.csdn.net/slowlifes/articl ...

  5. 「日常训练」Soldier and Badges (CFR304D2B)

    题意 (Codeforces 546B) 问对一个序列最少需要增减几个1能使其彼此不同. 分析 模拟处理.需要注意的是,尽管题目中说了an<=3000,问题是,如果一群a全是3000呢(滑稽), ...

  6. 菜鸟级appium 必看

    之所以写这个,因为太多新人,appium环境半天都搭建不好,版本问题,兼容问题等等. 自己的解决方案:1 官网下载nodejs,建议安装长期支持版 2 进入appium官网,点击下载,跳转到githu ...

  7. 学习人工智能的第五个月[字典学习[Dictionary Learning,DL]]

    摘要: 大白话解释字典学习,分享第五个月的学习过程,人生感悟,最后是自问自答. 目录: 1.字典学习(Dictionary Learning,DL) 2.学习过程 3.自问自答 内容: 1.字典学习( ...

  8. visionpro halcon 哪个好

    visionpro halcon 哪个好 很多朋友会问到visionpro和halcon这两款机器视觉软件,到底学哪个好呢,今天众寻网就给大家讲一讲: 首先比较下两者的优缺点: halcon: 提供的 ...

  9. kill命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/wangcp-2014/p/5146343.html 1.命令格式: kill[参数][进程号] 2.命令功能: 发送指 ...

  10. Linux 简单socket实现UDP通信

    服务器端 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sy ...