题目链接:http://poj.org/problem?id=1970

题意:

  有一个19 × 19 的五子棋棋盘,其中“0”代表未放入棋子,“1”代表黑色棋子,”2“代表白色棋子,如果某方的棋子在横,纵,斜这四个方向的连子数(连着的棋子数)恰好为5,那么此方就可以获胜。给你某一刻棋盘上的棋子状态,问你在此刻是哪一方获胜,亦或是平局,平局时仅输出“0”;如果是黑色方获胜,那么输出“1“,白色方获胜输出“2”,并且在第二行输出五连子最左边的棋子的坐标,如果在纵方向五连子,那么输出最上面的那个棋子的坐标。

思路:

  首先,对于一个棋子来说,它可以和八个方向的棋子连在一起形成连子,但是这里并用不着对棋子的八个方向进行搜索,因为八个方向实质上可以认为是四个方向,即只需对某个棋子的四个方向进行搜索就OK 了,方向的选择也会影响到程序的复杂性,这里的做法是选择一个当前棋子作为起点(0,0),对这个棋子的”“右上”(-1,1),“右”(0,1),“右下”(1,1),“下”(1,0)这四个方向进行搜索,原因是如果这四个方向能找到五连子,那么作为起点的棋子的坐标即是题目要求的最左边的棋子的坐标,可以降低程序复杂性。方向确定了,搜索的状态就确定了,对于每个棋子有四个状态,所以又需要一个辅助数组来标记棋子的某个状态是否已被搜索过,用一个三维数组visit[i][j][k]代表坐标为(i, j)的棋子其k方向是否已被搜索过,k取值为1~4。然后从左到右、从上到下遍历图,分别从四个方向搜索统计就好了。

  由于“右上”方向在搜索中的特殊性,所以这里要解释一些东西。在往“右上”方向搜索的过程中,如果一个棋子的“右上”方向没被搜索过,那么应该尽可能的往这个方向搜索(即使这个方向的其他棋子之前已被搜索过了,这里仍然要进行搜索)。

比如:

0 0 0 0 1...

0 0 0 1 0...

0 0 1 0 0...

0 1 0 0 0...

1 0 0 0 0...

...

首先搜索到的肯定是第一行的”1“,可知连子数为 1个, 但此时并不满足; 再搜索第二行的“1”,此时第一行的1虽然已经搜索过了,但是还需要再搜索一遍,可得连子数为2个; 当搜索到第三行的"1"时,上面的两个"1"仍然要进行搜索统计,可得连子数为3个......底下的两个“1”也是同理,虽然这里可以用记忆化,但是由于搜索树的层数并不深,所以影响不大。

然后当“右上”方向的延伸结果为5时,这里还需要判断“右上”这个方向的反方向(即右下)有没有一样的棋子(否则会出现6连子,不符合题意),之所以要判断“右上”的反方向是否有多余的棋子,是因为位于“右下”的棋子搜索顺序在当前棋子之后,所以“右下”若有相同的棋子,有可能使得本来的5连子形成6连子,但是“右”的反方向“左”、“右下”的反方向“右上”、"下"的反方向“上”,这三个反方向上的棋子的搜索顺序都在当前棋子之前,不用考虑是否会出现这个现象。

代码:

 #include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
#include <queue>
#include <algorithm>
#include <string> typedef long long LL;
using namespace std;
const int MAXN = ;
const int stepX[] = {, -, , , };//四个方向
const int stepY[] = {, , , , };
int visit[MAXN + ][MAXN + ][];//visit[i][j][k]表示位于[i][j]位置的棋子的k方向是否已被搜索过
int map[MAXN + ][MAXN + ];//存图
int cnt; void DFS(int x, int y, int id, int dire) {//x,y为坐标,id为1或者2,dire代表方位,即确定方位的进行搜索
visit[x][y][dire] = ;
int nex = x + stepX[dire], ney = y + stepY[dire];
if(map[nex][ney] == id){
++cnt;//统计连子数
DFS(nex, ney, id, dire);
}
} int main() {
//freopen("input", "r", stdin);
int t;
scanf("%d", &t);
while(t--) {
memset(visit, , sizeof(visit));
memset(map, , sizeof(map));
cnt = ;
for(int i = ; i <= ; i++) {
for(int j = ; j <= ; j++) {
scanf("%d", &map[i][j]);
}
}
int leftX = -, leftY = -;//五连子最左边棋子的坐标
int win = ;//获胜的标志
for(int i = ; i <= ; i++) {
for(int j = ; j <= ; j++) {
if(!map[i][j]) continue;
for(int k = ; k <= ; k++) {
if(!visit[i][j][k]) {
cnt = ;
DFS(i, j, map[i][j], k);
if(cnt == && map[i - stepX[k]][j - stepY[k]] != map[i][j]) {//判断是否为五连子且考虑反方向是否会造成六连子
win = map[i][j], leftX = i, leftY = j;
}
}
}
}
}
printf("%d\n", win);
if(win) printf("%d %d\n", leftX, leftY);
}
return ;
}

POJ 1970 The Game (DFS)的更多相关文章

  1. POJ 1321 棋盘问题 --- DFS

    POJ 1321 题目大意:给定一棋盘,在其棋盘区域放置棋子,需保证每行每列都只有一颗棋子. (注意 .不可放 #可放) 解题思路:利用DFS,从第一行开始依次往下遍历,列是否已经放置棋子用一个数组标 ...

  2. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  3. 【POJ - 1970】The Game(dfs)

    -->The Game 直接中文 Descriptions: 判断五子棋棋局是否有胜者,有的话输出胜者的棋子类型,并且输出五个棋子中最左上的棋子坐标:没有胜者输出0.棋盘是这样的,如图 Samp ...

  4. poj 3321 Apple Tree dfs序+线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K       Description There is an apple tree outsid ...

  5. 开篇,UVA 755 && POJ 1002 487--3279 (Trie + DFS / sort)

    博客第一篇写在11月1号,果然die die die die die alone~ 一道不太难的题,白书里被放到排序这一节,半年前用快排A过一次,但是现在做的时候发现可以用字典树加深搜,于是乐呵呵的开 ...

  6. poj 1416 Shredding Company( dfs )

    我的dfs真的好虚啊……,又是看的别人的博客做的 题目== 题目:http://poj.org/problem?id=1416 题意:给你两个数n,m;n表示最大数,m则是需要切割的数. 切割m,使得 ...

  7. poj 1129 Channel Allocation ( dfs )

    题目:http://poj.org/problem?id=1129 题意:求最小m,使平面图能染成m色,相邻两块不同色由四色定理可知顶点最多需要4种颜色即可.我们于是从1开始试到3即可. #inclu ...

  8. poj 3373 Changing Digits (DFS + 记忆化剪枝+鸽巢原理思想)

    http://poj.org/problem?id=3373 Changing Digits Time Limit: 3000MS   Memory Limit: 65536K Total Submi ...

  9. POJ 1699 Best Sequence dfs

    题目: http://poj.org/problem?id=1699 无意间A了..超时一次,加了一句 if(len > ans)return; 然后就A了,dfs题,没有太多好说的,代码写的效 ...

随机推荐

  1. 【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra

    题目描述 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 “doge” 的神秘生物 ...

  2. sql in()批量操作

    //批量修改 update 表A   set A.name='n'  where   A.id    in(字符串); //批量删除 delete  from    表名称 where  列名称   ...

  3. FAQ: SNMP on NetScaler Appliance

    FAQ: SNMP on NetScaler Appliance https://support.citrix.com/article/CTX122436 https://docs.citrix.co ...

  4. 【题解】Bzoj4316小C的独立集

    决定要开始学习圆方树 & 仙人掌相关姿势.加油~~ 其实感觉仙人掌本质上还是一棵树,长得也还挺优美的.很多的想法都可以往树的方面上靠,再针对仙人掌的特性做出改进.这题首先如果是在树上的话那么实 ...

  5. 杭电hdu 2089 数位dp

    杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍 ...

  6. python爬取七星彩的开奖历史记录

    1.因为人不可能一直无休止的学习,偶尔也想做点儿别的,昨天无聊就想写写Python,当然我承认我上班后基本都是在学工作方面的事情,在这个岗位我也呆了三年多了,还是那句话问我什么会不会我会给你说我啥都会 ...

  7. gitlab之:gitlab 403 forbidden 并发引起ip被封

    步骤: * 打开/etc/gitlab/gitlab.rb文件. * 查找gitlab_rails['rack_attack_git_basic_auth']关键词. * 取消注释 * 修改ip_wh ...

  8. Join EC2 into AD with SSM and remote powershell in AWS

    1.Create joinad.ps1 $username = "ad-domain\admin" $Password = "password" $pwd = ...

  9. Rem与em的简单理解

    Rem与em的简单理解 Em单位与像素px的转换 所得的像素值 = 当前元素的font-size * em的值 比如:div的font-size:12px 10em等同于120px 12*10 =12 ...

  10. 网络编程:connect函数

    TCP客户用connect函数来建立与TCP服务器的连接: cpp #include<sys/socket.h> int connect(int sockfd, const struct ...