时间限制:1000MS 内存限制:65535K
提交次数:566 通过次数:130
题型: 编程题 语言: G++;GCC
从前有一天,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; }