WUSTOJ 1336: Lucky Boy(Java)博弈
题目链接:1336: Lucky Boy
参考博客:LUCKY BOY 博弈——HandsomeHow
Description
Recently, Lur have a good luck. He is also the cleverest boy in his school as he create the most popular computer game – Lucky Boy. The game is played by two players, a and b, in 2d planar .In the game Lucky Boy, there are n different points on plane, each time one can remove one or multiple co-line points from the plane. The one who can firstly remove more than two points from the plane wins. The one who removes the last point on the plane can also win the game. You may assume that two players are both clever enough that they can always make the best choice. The winner is called Lucky Boy.
Given the n points, can you tell me who will be the Lucky Boy ? Note that player a will always the first one to remove points from the plane.
在一个二维平面,有 n 个不同的点,每次可以从平面上拿走一个点或者在一条直线上的多个点。先拿走两个以上的点或者拿走最后一个点的人获胜。问谁获胜?
Input
The first line of each case is an integer n(0<n<=103), following n lines each contains two integers x and y(0<=x, y<=108), describing the coordinates of each point. Ended by EOF.
Output
Output “a is the lucky boy.” in a single line if a win the game, otherwise you should output “b is the lucky boy.” in a single line.
Sample Input
3
0 0
1 1
2 2
3
0 0
1 1
2 3
4
0 0
1 1
2 2
3 5
4
0 0
0 1
1 1
1 0
Sample Output
a is the lucky boy.
b is the lucky boy.
a is the lucky boy.
a is the lucky boy.
分析💬
(⊙o⊙)…博弈的题目我做的还是有点少,看起来不难,我也不会做。。。感觉我阅读有问题😳
思路来源于参考博客。
- 至少3个点在一条直线上,a肯定获胜,因为他先手。
- 最多2个点在一条直线上,如果a想要获胜,那么最后1个或2个点必须要自己拿,因此他应该给b留3个点,要想给b留3个点,那么前一步a必须要给b留6个点。也就是说只要a拿完后将点的个数保持为3m即可获胜。
- 所以如果n不是3的倍数,那么a一定获胜。
- 如果是3的倍数,那么a一定输。
按照上面方法:1、先判断是否有3个点在一条直线上;2、判断是否是3的倍数。
很明显第一步要三层循环,第二步只需要一个if判断。因此应该将第二步作为先行判断条件,从而减小进入循环的可能性。即:
- n不是3的倍数
- 至少3个点在一条直线上,a胜
- 最多2个点在一条直线上,a胜
- n是3的倍数
- 至少3个点在一条直线上,a胜
- 最多2个点在一条直线上,a输
代码💻
/**
* Time 634ms
* @author wowpH
* @version 1.0
* @date 2019年6月29日下午10:05:57
* Environment: Windows 10
* IDE Version: Eclipse 2019-3
* JDK Version: JDK1.8.0_112
*/
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();// 点的个数
int[][] p = new int[n][2];// 保存坐标
for (int i = 0; i < n; ++i) {
p[i][0] = sc.nextInt();
p[i][1] = sc.nextInt();
}
boolean aWin = false;// 初始a输
if (0 != n % 3) {
aWin = true;// 不是3的倍数,a获胜
} else {// 是3的倍数
// 判断是否有3个点在一条直线
for (int i = 0; i < n && false == aWin; ++i) {
for (int j = i + 1; j < n && false == aWin; ++j) {
for (int k = j + 1; k < n && false == aWin; ++k) {
int a = (p[i][0] - p[j][0]) * (p[i][1] - p[k][1]);
int b = (p[i][0] - p[k][0]) * (p[i][1] - p[j][1]);
if (a == b) {
aWin = true;// 点i,j,k在一条直线,a获胜
}
}
}
}
}
if (true == aWin) {
System.out.println("a is the lucky boy.");
} else {
System.out.println("b is the lucky boy.");
}
}
sc.close();
}
}