【洛谷 P2346】四子连棋(状态压缩,搜索)
其实这题可以直接二进制状压做,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】四子连棋(状态压缩,搜索)的更多相关文章
- 洛谷P2346四子连棋
题目描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步. 黑白双方交替走棋,任意一方可 ...
- P2346 四子连棋
P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...
- Codevs 四子连棋 (迭代加深搜索)
题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双 ...
- 洛谷 P2704 [NOI2001]炮兵阵地 (状态压缩DP+优化)
题目描述 司令部的将军们打算在NM的网格地图上部署他们的炮兵部队.一个NM的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P" ...
- 洛谷 P1896 [SCOI2005]互不侵犯 (状态压缩DP)
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...
- 洛谷 P2622 关灯问题II (状态压缩+BFS)
题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...
- 【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋
一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的( ...
- codevs1004四子连棋[BFS 哈希]
1004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...
- Codevs p1004 四子连棋
四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向 ...
随机推荐
- 【Luogu P1935】[国家集训队]圈地计划
题目 最近房地产商 GDOI (Group of Dumbbells Or Idiots) 从 NOI (Nuts Old Idiots) 手中得到了一块开发土地. 据了解,这块土地是一块矩形的区域, ...
- 序列化反序列化--Xstream的使用
之前讲了fastjson的使用--将JavaBean与json对象之间互相转换. 该篇文章,教大家使用Xstream来实现XMl与JavaBean的转换. 第一步: 通过maven引入XStream的 ...
- Sql面试题之三(难度:简单| 含答案)
Sql面试题之三(难度:简单| 含答案) 答案: .SELECT B.name, B.Depart T.Content FROM B, T WHERE ( T.Content = '税法培训' and ...
- Spring实战第九章学习笔记————保护Web应用
保护Web应用 在这一章我们将使用切面技术来探索保护应用程序的方式.不过我们不必自己开发这些切面----我们将使用Spring Security,一种基于Spring AOP和Servlet规范的Fi ...
- ActiveRecord-连接多张表之单表继承
ActiveRecord-连接多张表之单表继承 1. 基本概念 Rails提供了两种机制,可以将复杂的面向对象模型映射为关系模型,即所谓的单表继承(single-table inheritance)和 ...
- Cassandra - Insert after Delete fails silently
在delete一条数据后,再insert 相同内容的数据,结果看起来是成功的,但是当你去查找这个数据,却没有任何内容,整个过程并且没有任何异常提示. 这往往发生在单元测试的时候,我们反复清理和写入数据 ...
- 【虚拟货币钱包】从 BIP32、BIP39、BIP44 到 Ethereum HD Wallet
干货 | [虚拟货币钱包]从 BIP32.BIP39.BIP44 到 Ethereum HD Wallet {{uploading-image-882090.png(uploading...)}}
- linux备忘录-shell脚本
知识 shell执行方式 shell执行方式有 通过source或. 在现在的bash环境中执行脚本 变量等会保持 通过bash shell.sh或sh shell.sh 使用一个新的bash环境执行 ...
- POJ 1149 PIGS(最大流)
Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock an ...
- winform label去背景
以pictureBox上面显示一个不需要背景的label为例: 1.保证label的父控件是该pictureBox: 2.label的color属性为transParent: