Loading

【题解】P6369[COCI2006-2007#6] MARATON

蒟蒻题解首祭!!!

咕了三星期了

题目传送门

先分析下题意:
一个由各个字母与 ‘.’ 组成的正方形矩阵(边长小于等于30)

求任意行列斜线上有没有3个连续相同的字母。

就这,无了。

思考下算法

数据范围很小(只有30),我们为什么不用最无脑的遍历枚举呢?

输入就不用多说了,一个字符型数组,但要注意声明时,冗余要稍多一些,防止访问越界。

for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
		cin>>MAP[i][j];

遍历判断:
某玩家若胜利则此玩家字母连线必定为以下四情况之一

设遍历到的这个位置坐标为(x,y)

类 型 坐标1 坐标2 坐标3
(x-1,y) (x,y) (x+1,y)
(x,y+1) (x,y) (x,y-1)
斜线 (x-1,y+1) (x,y) (x+1,y-1)
斜线 (x+1,y-1) (x,y) (x-1,y+1)

判断函数:

void JUDGE(int x,int y)
{
	if((MAP[x-1][y]==MAP[x][y])&&(MAP[x+1][y]==MAP[x][y]))
		OUT(MAP[x][y]);
	if((MAP[x][y-1]==MAP[x][y])&&(MAP[x][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);
	if((MAP[x-1][y-1]==MAP[x][y])&&(MAP[x+1][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);
	if((MAP[x+1][y-1]==MAP[x][y])&&(MAP[x-1][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);
}

这个时候数组冗余就发挥作用了,可以略去越界判断只需要输出时进行一次特判就可以。

输出函数:

void OUT(char c)
{
	if(c!='.'&&c!=0)
	{	
		printf("%c",c);
		sign=false;
	}
}

此外,我们还需要一个sign变量(bool)记录是否有赢家,以此判断是否输出"ongoing"

if(sign)
	printf("ongoing");

完整代码(20ms,660.00KB):

#include<bits/stdc++.h>
using namespace std;

int n;
char MAP[35][35];
bool sign=true;//记录是否有赢家
void JUDGE(int,int),OUT(char);

int main()
{
	memset(MAP,0,sizeof(MAP));
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>MAP[i][j];
	for(int i=1;i<=n&&sign;i++)//循环必须判断sign情况 不然可能重复输出
		for(int j=1;j<=n&&sign;j++)
			JUDGE(i,j);
	if(sign)//若遍历后无赢家输出"ongoing"
		printf("ongoing");
	return 0;
}

void JUDGE(int x,int y)
{
	if((MAP[x-1][y]==MAP[x][y])&&(MAP[x+1][y]==MAP[x][y])) 
		OUT(MAP[x][y]);//行
	if((MAP[x][y-1]==MAP[x][y])&&(MAP[x][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);//列
	if((MAP[x-1][y-1]==MAP[x][y])&&(MAP[x+1][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);//斜线
	if((MAP[x+1][y-1]==MAP[x][y])&&(MAP[x-1][y+1]==MAP[x][y]))
		OUT(MAP[x][y]);//斜线
}

void OUT(char c)
{
	if(c!='.')//棋盘中可能有连续3个'.'构成的线
	{	
		printf("%c",c);
		sign=false;//更新sign
	}
}

完结撒fa~

posted @ 2020-10-14 20:01    阅读(181)  评论(0编辑  收藏  举报