五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。通 常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者 获胜。
五子连珠是在横. 线. ,纵. 线. ,斜. 线. ,反. 斜. 线. 四个方向上形成五. 子. 及. 以. 上. 的连线,当出现多于五子的连珠时,也只记为一. 次. 五子连珠。
五. 子. 连. 珠. 总. 数. 等于棋局中的所有方向上的五子连珠连线的数量之和。
我们想知道,给定一个长宽皆为 n 的棋局,白. 棋. 落在哪些点可以增. 加. 白. 棋. 五. 子. 连.
珠. 总. 数. ?
对增. 加. 白. 棋. 五. 子. 连. 珠. 总. 数. 的举例说明 (A 点为我们选择的落点): 1
wwwwAbbbb
落白棋之前未形成五子连珠,落入白棋之后,五子连珠总数加一,满足要求。
2
wwwwwAbbbb
落白棋之前已经形成五子连珠,落白棋之后,五子连珠总数不变,不满足要求。
3
wwwwwAwwwww
落白棋之前五子连珠总数为二,落入白棋之后,两边连成一线,五子连珠总数减 一,不满足要求。
4
*w***w*****
**w**w*****
***w*w*****
****ww***** wwwwwAwwwww
落白棋之前五子连珠总数为二。落入白棋之后,两边连成一线,斜向和纵向形成新 的五子连珠,总数为三。五子连珠总数加一,这个点满足要求。
从标准输入读入数据。
输入为第一行为一个数字 n(n ≤ 40),表示棋盘大小。
接下来的 n 行,每行为 n 个字符,可能有三种字符,* 表示无棋子,b 表示黑棋,
w 表示白棋。
输入棋局中可能已. 经. 有. 五. 子. 连. 珠. 的情况,我们需要计算能增. 加. 白. 棋. 五. 子. 连. 珠. 总. 数. 的白棋落点。
输出到标准输出。
输出为 k 行,包括 k 个满足要求的落点,k 个点按照从. 左. 至. 右. ,从. 上. 至. 下. 的顺序输出,即先按行排序,再按列排序输出。
每行为一个点坐标 x y,分别表示列坐标,行坐标,以空格分隔,坐标序号从 0 开始,棋盘左上角为原点。
*a***
*****
*****
*****
***b*
图中 a 点的坐标为 1 0,b 点的坐标为 3 4。
8
****b*bb
*****b*b bb*bbbw* w*wbwwww bwwbwwbw ww**wbbw
*bww***w
***bwb*b
7 2
2 5
3 5
4 6
2 7
测试点 |
说明 |
1,2 |
没有满足要求的点 |
3,4,5,6,7,8 |
只需要计算横纵方向, 棋局中不存在旧的五子连珠 |
9,10,11,12,13,14 |
需要计算所有方向, 棋局中不存在旧的五子连珠 |
15,16,17,18,19,20 |
盘面上存在旧的五子连珠 |
自己写了一遍,也不知道对不对,ccsp简直了,题解都木有
#include
#include
using namespace std;
#define MAX_N 43
char q[MAX_N][MAX_N];
int heng[MAX_N][MAX_N];
int zong[MAX_N][MAX_N];
int xie[MAX_N][MAX_N];
int fanxie[MAX_N][MAX_N];
int n;
//右
bool heng_(int i,int y)
{
if(y+5>n) return false;
// printf("\n");
for(int j = y; j < n; j++){
// printf("%c",q[i][j]);
if((q[i][j]!='w'||heng[i][j]) && j < y+5) return false;
}
// printf("\n");
for(int j = y; j < n; j++){
if(q[i][j]=='w') heng[i][j] = 1;
else break;
}
//printf("heng:x=%d,y=%d\n",i,y);
return true;
}
//右下
bool fanxie_(int x,int y)
{
if(x+5>n||y+5>n) return false;
for(int i = x,j = y; i < n && j < n; i++,j++){
if((q[i][j]!='w'||fanxie[i][j]) && i < x+5) return false;
}
for(int i = x,j = y; i < n && j < n; i++,j++){
if(q[i][j]=='w') fanxie[i][j] = 1;
else break;
}
// printf("fanxie:x=%d,y=%d\n",x,y);
return true;
}
//下
bool zong_(int x,int j)
{
if(x+5>n) return false;
for(int i = x; i < n; i++){
if((q[i][j]!='w'||zong[i][j]) && in||y-5<-1) return false;
for(int i = x,j = y; i < n && j >= 0; i++,j--){
if((q[i][j]!='w'||xie[i][j]) && i < x+5) return false;
}
for(int i = x,j = y; i < n && j >= 0; i++,j--){
if(q[i][j]=='w') xie[i][j] = 1;
else break;
}
// printf("xie:x=%d,y=%d\n",x,y);
return true;
}
//计算五子连珠数
int fun()
{
//初始化
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
heng[i][j] = 0;
zong[i][j] = 0;
xie[i][j] = 0;
fanxie[i][j] = 0;
}
}
int ans = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(q[i][j]=='w'){
if(heng_(i,j)) ans++;
if(fanxie_(i,j)) ans++;
if(zong_(i,j)) ans++;
if(xie_(i,j)) ans++;
}
}
}
//cout <<"ans="<> n;
for(int i = 0; i < n; i++){
getchar();
for(int j = 0; j < n; j++){
scanf("%c",&q[i][j]);
}
}
cnt = fun();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(q[i][j]=='*'){
q[i][j] = 'w';
//printf("%d %d\n",i,j);
if(fun() > cnt)
printf("%d %d\n",j,i);
q[i][j] = '*';
}
}
}
return 0;
}
//test样例
//8
//****b*bb
//*****b*b
//bb*bbbw*
//w*wbwwww
//bwwbwwbw
//ww**wbbw
//*bww***w
//***bwb*b