【问题描述】
有N个小朋友在玩石头剪刀布的游戏(循环赛,任意两个人之间进行且只进行一局游戏)。现在已经知道了他们两两之间的输赢情况。
定义石头剪刀布局面为:有三个人i,j,k,满足:i赢了j,j赢了k,k赢了i,那么这个三元组(i,j,k)就被叫做石头剪刀布局面。
现在kAc想知道一共有多少个石头用剪刀布局面呢?
注意(i,j,k)(j,k,i) (k,i,j)被视为是相同的,之计数一次。
【输入格式】
第一行一个整数N。
接下来N行每行N个字符。其中第i行的第j个字符可能是:
-:表示i=j。
Y:表示i赢了j。
N:表示i输给了j。
保证第i行的第j个字符和第j行的第i个字符,必然恰好一个是Y,另一个是N。
【输出格式】
一个整数,表示所求局面的数量。
【样例输入】
4
-YNN
N-YY
YN-Y
YNN-
【样例输出】
2
【过程分析】
共分为两步,第一步:
找出所有的石头剪刀布局面
1.对于输入的二维数组,i代表行数,j代表列数,从第0行开始遍历0到n-1列找出所有的Y,直到把n-1行遍历完毕,这一个操作是为了找出石头剪刀布局面的第一环,i赢了j。
2.在找到Y之后,再将j作为行数,开始遍历0到n-1列,找出所有的Y,将其列数标记为k,这一步是为了找出石头剪刀布局面的第二环,j赢了k。
3.标记了k之后,判断在二维数组中,下标为【k】【i】的值是否是Y,这一步是为了找出石头剪刀布局面的第三环,k赢了i。
这三步之后,下标为[i][j],[j][k],[k][i]的便符合石头剪刀布局面。
用一个二维数组将其存储起来,进行第二步。
第二步:
把重复的石头剪刀布局面删掉
记局面数为num,每当出现一个新局面时,操作默认局面数加一,把新局面与之前的num个局面进行比较,诺出现重复,跳出循环,局面书减一,即可达到删掉重复的局面数。
最后输出局面数。
具体详情见代码
#include<stdio.h>
int main(){
int N;
char outcome[10][10];
scanf("%d",&N);
getchar(); //因为后面要输入字符,必须用这一操作把scanf残留的回车去掉
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N;j++){
scanf("%c",&outcome[i][j]);
}
getchar();
}
int sign[120][3]; //存储石头剪刀布局面
int k,h,p,q,m;
int num=0;
for(i=0;i<N;i++){
for(j=0;j<N;j++){
if(outcome[i][j]=='Y'){
for(k=0;k<N;k++){
if(outcome[j][k]=='Y'){
if(outcome[k][i]=='Y'){
sign[num][0]=i;
sign[num][1]=j;
sign[num][2]=k;
for(h=num-1;h>=0;h--){ //去掉重复的局面
m=0;
for(p=0;p<3;p++){
for(q=0;q<3;q++){
if(sign[num][p]==sign[h][q]){
m++;
}
}
}
if(m==3){
num--;
break;
}
}
num++;
}
}
}
}
}
}
printf("%d",num);
return 0;
}