题目
你可能听说过“石头剪刀布”的游戏。
这个游戏在牛当中同样流行,它们称之为“蹄子剪刀布”。
游戏的规则非常简单,两头牛相互对抗,数到三之后各出一个表示蹄子,剪刀或布的手势。
蹄子赢剪刀,剪刀赢布,布赢蹄子。
例如,第一头牛出“蹄子”手势,第二头牛出“布”手势,则第二头牛获胜。
如果两头牛出相同的手势,则算平局。
农夫约翰的两头奶牛正在进行 N 轮“蹄子剪刀布”对抗,他看的十分入迷。
不幸的是,虽然他可以看到奶牛正在做出三种不同类型的手势,但他却无法分辨出哪一个代表“蹄子”,哪一个代表“布”以及哪一个代表“剪刀”。
不知道这三种手势的具体含义的情况下,农夫约翰给这三种手势分配了编号 1,2,3。
手势 1 可能代表“蹄子”,可能代表“剪刀”,也可能代表“布”,反正他傻傻分不清楚。
给出两头奶牛在 N 场比赛中所做出的具体手势对应的编号,请你判断第一头奶牛最多可能赢多少盘对抗。
输入格式
第一行包含整数 N。
接下来 N 行,每行包含两个整数(1 或 2 或 3),表示两头奶牛在一轮对抗中所出的手势对应的编号。
输出格式
输出第一头奶牛可能获胜的最大场次数。
数据范围
1 ≤ N ≤ 100
输入样例:
5
1 2
2 2
1 3
1 1
3 2
输出样例:
2
样例解释
此样例的一种解决方案是,1 表示剪刀,2 表示蹄子,3 表示布。
这样,第一头奶牛可以赢得 (1,3) 和 (3,2) 两场比赛。
解题思路
首先,对于1,2,3 三个数,有以下八种排列方式:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
这八种排列方式分别对应以下八种赢的方式:
1 2 3 -> 1 赢 2,2 赢 3,3 赢 1
1 3 2 -> 1 赢 3,3 赢 2,2 赢 1
2 1 3 -> 2 赢 1,1 赢 3,3 赢 2
2 3 1 -> 2 赢 3,3 赢 1,1 赢 2
3 1 2 -> 3 赢 1,1 赢 2,2 赢 3
3 2 1 -> 3 赢 2,2 赢 1,1 赢 3
当我们将这八种方式画成环后,其实只有如下图的两种方式:
对于上面那张图来说:
即 1 赢 2,2 赢 3,3 赢 1;
也就是第一头牛出的值与第二头牛出的值之差为 -1 和 2 时获胜;
对下面那张图来说:
1 赢 3,3 赢 2,2 赢 1;
也就是第一头牛出的值与第二头牛出的值之差为 -2 和 1 时获胜;
而如果二者出的相同,第一头牛出的值与第二头牛出的值之差为0,则平局,无需考虑。
所以我们只要将第一头牛出的值与第二头牛出的值之差为 -2 和 1 之和 与 第一头牛出的值与第二头牛出的值之差为 -2 和 1 之和作比较,较大的就是第一头牛可能赢的最大次数。
AC 代码
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class Main1801 {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
int n = Integer.parseInt(in.readLine());
int[] win = new int[5];
while(n-- > 0) {
String str = in.readLine();
// 1 赢 2,2 赢 3, 3 赢 1 时
// -1 代表 1 赢 2,2 赢 3 的情况,对应下标 1
// 2 代表 3 赢 1 的情况,对应下标 4
// 1 赢 3,3 赢 2, 2 赢 1 时
// 1 代表 3 赢 2,2 赢 1 的情况,对应下标 3
// -2 代表 1 赢 3 的情况,对应下标 0
win[Integer.parseInt(str.split(" ")[0]) - Integer.parseInt(str.split(" ")[1]) + 2]++;
}
// 下标 1 和 4 对应 1 赢 3,3 赢 2, 2 赢 1 的情况
// 下标 0 和 3 对应 1 赢 2,2 赢 3, 3 赢 1 的情况
out.print(Math.max(win[1] + win[4], win[0] + win[3]));
out.flush();
in.close();
}
}
C++
#include<iostream>
using namespace std;
int n;
int win[5];
int main()
{
scanf("%d", &n);
while(n--)
{
int a = 0;
int b = 0;
scanf("%d%d", &a, &b);
// 1 赢 2,2 赢 3, 3 赢 1 时
// -1 代表 1 赢 2,2 赢 3 的情况,对应下标 1
// 2 代表 3 赢 1 的情况,对应下标 4
// 1 赢 3,3 赢 2, 2 赢 1 时
// 1 代表 3 赢 2,2 赢 1 的情况,对应下标 3
// -2 代表 1 赢 3 的情况,对应下标 0
win[a - b + 2]++;
}
// 下标 1 和 4 对应 1 赢 3,3 赢 2, 2 赢 1 的情况
// 下标 0 和 3 对应 1 赢 2,2 赢 3, 3 赢 1 的情况
printf("%d", max(win[0] + win[3], win[1] + win[4]));
return 0;
}