11155 ly与lyon的终极巅峰对决
时间限制:1000MS 内存限制:65535K
提交次数:566 通过次数:130
题型: 编程题 语言: G++;GCC
Description
从前有一天,ly与lyon在讨论人工智能里面的博弈问题,恰好,他们提到了五子棋。 当然,这里说的五子棋是指无禁手(不知道什么是禁手的也不用管了,跟这题没关系)的五子棋: 黑先下,黑白轮流下,最先在横竖斜任一方向上形成连续的5个子(或以上)就算赢。 对此,ly和lyon都有自己的一套判断局势的算法,并且根据自己的想法各写了一个判断局况的程序。然而,他们都觉得自己的程序要比对方的优秀,所以, 他们稍作改良,做成了自动决策的对局程序,并拿出来互相pk。目前需要一个自动判断胜负的程序,即最先出现5连子的判胜。
输入格式
第1行输入两个数n和m,用空格分开,n为棋盘横纵坐标的最大值,m为步数: 1<=n<=1000,0<m<=n*n 第2行到第m+1行为第一步到第m步的坐标,每行两个数,用空格分开: x和y,1<=x,y<=n 输入保证不存在重复下子。 (出题人LRC)
输出格式
输出首次分出胜负那一步的序号(第一步为1),如果走完了都没有分出胜负,输出“baga”。
输入样例
5 11 3 3 2 3 2 4 4 3 4 2 3 4 1 5 3 2 5 1 1 1 1 2
输出样例
9
思路:这道题不难。关键在于如何判断每一步下完后,下棋的人能否赢。我们用一个函数去判断每一步下完后,能否是横斜竖任意方向组成连续5个棋。详细见代码。
#include <stdio.h>
#include <stdlib.h>
int black[1001][1001],white[1001][1001],n;
int judge(int test[][1001],int a,int b)//判断这一步后,各个方向能否构成连续5子
{
int i,j,k,sum1,sum2,sum3,sum4;//sum1-4记录横,竖,45°斜,135°斜方向连续5个方向位置的值的和
for(k=0;k<=4;k++)
{
sum1=sum2=sum3=sum4=0;
for(i=a+4-k;i>=a-k;i--)//横方向
{
if(i<=n&&i>=1)//保证不超过象限范围
sum1+=test[i][b];
if(sum1==5)
return 1;//如果可以构成连续5子,返回1
}
for(i=b+4-k;i>=b-k;i--)//竖方向
{
if(i>=1&&i<=n)
sum2+=test[a][i];
if(sum2==5)
return 1;
}
for(i=b+4-k,j=a+4-k;i>=b-k&&j>=a-k;j--,i--)//斜方向
{
if(i>=1&&i<=n&&j>=1&&j<=n)
sum3+=test[j][i];
if(sum3==5)
return 1;
}
for(i=b+4-k,j=a-4+k;i>=b-k&&j<=a+k;j++,i--)//斜方向
{
if(i>=1&&i<=n&&j>=1&&j<=n)
sum4+=test[j][i];
if(sum4==5)
return 1;
}
}
return 0;//不能则返回0
}
int main()
{
int a,b,m,i,j,s1=0,s2=0,judge1=0,judge2=0;//s1,s2分别记录黑棋和白棋赢时是第几步,都没有赢,则都为0
scanf("%d %d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
if(i%2!=0)//单数黑棋下
{
black[a][b]=1;//这个位置标记为1
if(s1==0)//如果s1>0了,证明已经赢了,没必要再去判断
{
judge1=judge(black,a,b);
if(judge1==1)
s1=i;
}
}
else//双数白棋
{
white[a][b]=1;
if(s2==0)
{
judge2=judge(white,a,b);
if(judge2==1)
s2=i;
}
}
}
if(s1>0&&s2>0)//按要求输出
{
if(s1>s2)
printf("%d",s2);
else
printf("%d",s1);
}
else if(s1>s2)
printf("%d",s1);
else if(s1<s2)
printf("%d",s2);
else
printf("baga");
return 0;
}