阿里九游开放平台近日上架了一款新的益智类游戏——成三棋。成三棋是我国非常古老的一个双人棋类游戏,其棋盘如下图所示:
成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋子。我们可以用坐标系来描述棋盘:
如果一条线段上的三个交叉点都被同一玩家的棋子占据的话,则称这条线段被该玩家 成三。现在,小红和小明两人在游戏平台上下棋,其中小红的棋子是黑色的。请你帮小红计算他成三的线段数。
样例对应的棋盘如下:
输入格式
输入第一行两个整数 n,m(3 \le n, m \le 9)n,m(3≤n,m≤9),nn 表示小红的棋子数,mm 表示小明的棋子数。
接下来 nn 行输入小红的棋子坐标。
接下来 mm 行输入小明的棋子坐标。
输入保证坐标合法,并且棋子之间不重合。
输出格式
输出小红成三的线段数。
样例输入
6 3
-1 0
-2 0
-3 0
-1 -1
-1 1
1 0
0 2
0 3
2 2
样例输出
2
我的思路比较简单,先把输入的数据存放在二维数组a[10][2]里,然后分别以行、列的方式遍历该数组,对该数组中横、纵坐标相同的点进行分类,-3到3的7个数字,num[7]对在每一条纵线和横线上的点进行统计,从而知道每一个线段方向上有几个点,b[7][6]则是记录横坐标或者纵坐标相同的点记录另一维的数字,以便之后判断是否在一条线段上。
在judge函数里,如果一个线段方向上有超过3个点,若这个数字不是0,那么肯定只有三个点,而且这三个点在一条线段上(从图里可以看出)。如果这个数字是0,可以对b[i][]里存的数字进行排序,先从小到大,如果前三个数字分别是-3,-2,-1,那么肯定符合要求,再从大到小排序,如果前三个数字分别是3,2,1,也是符合要求的。之所以进行两次排序判断,是因为可能有6个点,在两条线段上。
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int Point_num,useless,a[10][2]={-99},b[7][6]={-99},so=0;
int num[7]={0};
void judge()
{
int *p,i;
for(i=0;i<7;i++)
{
if(num[i]>2)
{
p=b[i];
if(i!=3)
so++;
else
{
sort(p,p+num[i],less<int>());
if(p[0]==-3 && p[1]==-2 &&p[2]==-1)
so++;
sort(p,p+num[i],greater<int>());
if(p[0]==3 && p[1]==2 &&p[2]==1)
so++;
}
}
}
}
void d(int c)
{
int i,j;
for(i=0;i<7;i++)
{
num[i]=0;
for(j=0;j<6;j++)
b[i][j]=-99;
}
for(i=0;i<Point_num;i++)
{
j=a[i][c]+3;
b[j][num[j]++]=a[i][1-c];
}
}
int main(){
int i,j,k;
cin>>Point_num>>useless;
for(i=0;i<Point_num;i++)
cin>>a[i][0]>>a[i][1];
for(i=0;i<useless;i++)
cin>>j>>k;
for(i=0;i<2;i++)
{
d(i);
judge();
}
cout<<so;
}