【题解】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~