codevs四子连棋--搜索
来源:互联网 发布:移动协同软件最新版 编辑:程序博客网 时间:2024/05/16 16:11
【codevs1004】四子连棋
题目描述 Description
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
●○● ○●○●●○●○○●○
输入描述 Input Description
输出描述 Output Description
用最少的步数移动到目标棋局的步数。
样例输入 Sample Input
BWBO
WBWB
BWBW
WBWO
样例输出 Sample Output
5
题解
这显然是一道搜索相关的题目,每次找到空白的格子,将其与四周的棋子进行交换
这类求最小步数的题目往往迭代深搜可以秒杀
如果使用广度搜索,由于总局面数达到4 * 10^7,我们需要对局面进行判重,剪除重复搜索的分枝
这就需要用到哈希表,将局面看做16位的三进制数,转换十进制后取模作为key
据说迭代深搜可以秒杀
本题代码不考虑哈希表冲突的情况,不过由于最少步数的情况较多,得到错解的可能性比较低
valid函数用于与空白格交换的格子的合法性
equal用于判断四个字符是否相等
check用于判断是否为最终局面
gethash用于计算局面的哈希值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define inf 1000000000
#define ll long long
#define mod 9875321
using namespacestd;
llread()
{
llx=0,f=1;charch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
returnx*f;
}
int head,tail=2,ans=-1;
boolmp[10000005],last[1000005];
int xx[4]={0,0,1,-1},yy[4]={-1,1,0,0};
chara[5][5];
char q[1000005][5][5];
intstep[1000005];
bool valid(intx,inty,intt)
{
if(x>4||y>4||x<1||y<1||a[x][y]=='O')return0;
if(a[x][y]=='B'&&t==0)return0;
if(a[x][y]=='W'&&t==1)return0;
return1;
}
boolequal(chara,charb,charc,chard)
{
if(a!=b||b!=c||c!=d)return0;
return1;
}
bool check(chara[5][5])
{
for(inti=1;i<=4;i++)
{
if(equal(a[i][1],a[i][2],a[i][3],a[i][4]))return1;
if(equal(a[1][i],a[2][i],a[3][i],a[4][i]))return1;
}
if(equal(a[1][1],a[2][2],a[3][3],a[4][4]))return1;
if(equal(a[1][4],a[2][3],a[3][2],a[4][1]))return1;
return0;
}
intgethash(chara[5][5])
{
intt=0,key=0;
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
{
if(a[i][j]=='O')t=0;
if(a[i][j]=='W')t=1;
if(a[i][j]=='B')t=2;
key=(key*3+t)%mod;
}
returnkey;
}
void move(intx,inty)
{
for(intk=0;k<4;k++)
{
inttx=x+xx[k],ty=y+yy[k];
if(!valid(tx,ty,last[head]))continue;
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
a[i][j]=q[head][i][j];
swap(a[x][y],a[tx][ty]);
if(mp[gethash(a)])continue;
mp[gethash(a)]=1;
tail++;
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
q[tail][i][j]=a[i][j];
step[tail]=step[head]+1;
last[tail]=last[head]^1;
if(check(a))ans=step[tail];
}
}
voidbfs()
{
while(head!=tail)
{
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
if(q[head][i][j]=='O')
move(i,j);
if(ans!=-1)return;
head++;
}
}
intmain()
{
for(inti=1;i<=4;i++)
scanf("%s",a[i]+1);
for(inti=1;i<=4;i++)
for(intj=1;j<=4;j++)
q[0][i][j]=q[1][i][j]=a[i][j];
last[0]=0;last[1]=1;
bfs();
printf("%d",ans);
return0;
}
阅读全文
0 0
- codevs四子连棋--搜索
- codevs 1004 四子连棋 迭代加深搜索
- codevs 1116四色问题 DFS搜索
- 【CodeVS】1229 数字游戏 开放性 搜索 Hash
- codevs#1116 [题解]四色问题 [key.搜索 dfs]
- 【codevs】2152 滑雪 记忆化搜索
- Codevs 2152 滑雪 记忆化搜索DP
- Codevs 搜索刷题 集合篇
- codevs 1068 乌龟棋(记忆化搜索)
- codevs 2594 解题报告 启发式搜索
- codevs 2152 滑雪 搜索 解题报告
- Codevs P1004 四子连棋
- 【codevs 1004】四子连棋
- 【CodeVS 1004】四子连棋
- CODEVS 1004 四子连棋
- codevs天梯 四子连棋
- Codevs 1004 四子连棋
- CodeVS 1004 四子连棋
- eclipse安装使用教程
- 数据分析工具R和RStudio入门介绍
- Python idle安装与使用教程 调试、下载
- VMWare虚拟机安装创建虚拟机的使用教程
- Java开发中的23种设计模式详解
- codevs四子连棋--搜索
- &和&&的区别
- 二叉树和二叉查找树之间的区别
- R语言中的数据处理包dplyr、tidyr笔记
- ggplot2作图详解:入门函数qplot
- R语言两种方式求指定日期所在月的天数
- MySQL深入(三)
- MapReduce的Shuffle过程介绍
- MapReduce计数器