小花梨的取石子游戏——java

news/2024/7/5 18:33:27 标签: 博弈论, 思维

小花梨的取石子游戏


Problem D、小花梨的取石子游戏
时间限制:1000ms 空间限制:512MB
Description
小花梨有?堆石子,第?堆石子数量为??,?堆石子顺时针编号为1 − ?(如图)。
游戏将进行?轮,每轮游戏单独进行,互不干扰,每轮初始时第?堆石子数目为??。
第?轮从编号为?的那堆石子为起点,顺时针来取石子。两人轮流取石子,不可不取,最少取
一个石子,最多把当前这一堆取完,只有取完一堆后才走到下一堆石子。走完一圈后石子都
被取完,不能取石子的人就失败。假设两人以最优策略进行取石子操作,请分别输出?轮游
戏是先手胜还是后手胜。
Input
第一行为正整数?,表示石子的堆数 (1 ≤ ? ≤ 100000)
第二行输入?个正整数表示每一堆的石子数目??(1 ≤ ?? ≤ 109
)
Output
输出?行,第?行表示第?轮游戏的结果。如果先手胜则输出"?????",后手胜输出"??????"。
Example
Sample Input Sample Output
3
2 1 3
First
Second
First
2
2 2
First
First
Note
样例1:
游戏进行3轮
第1轮游戏石子堆下标的顺序为1 2 3,此时石子数目按顺序为2 1 3,先手胜
第2轮游戏石子堆下标的顺序为2 3 1,此时石子数目按顺序为1 3 2,后手胜
第3轮游戏石子堆下标的顺序为3 1 2,此时石子数目按顺序为3 2 1,先手胜

接下来先说一下我对这道题的看法:
当看到这道题的时候我发现它是一个博弈论;于是我便开始拿着我的板子判断它是属于尼姆博弈,巴什博弈和威佐夫博弈中的哪一种,结果发现,哪一种也不是,所以我认为它是一道思维题;
不断在WA中探索正确的道路,终于被我找到了,但可能是由于复杂度太高,导致超时,还好最后改进了一下,过了。
在这道题中,一共wa了貌似是19次,很悲,希望在比赛的过程中一定要细心一点,不要看着接过去改程序了,考虑要全面一点;
接下来说一下这一题的算法,由于本人表达能力不好,又与题解考虑得近乎一样,就直接用题解了,原谅;

  1. 现在只考虑每一轮游戏;

  2. 一堆的时候是必胜态;

  3. 多堆的时候:
    起点数目大于1,是必胜态
    因为可以取完或者取得只剩下一个,这两种状态的胜负一定不同,也就是说一定可以到达必败状态,所以此时为必胜态;

    起点数目等于1,和下一点的状态相反;(我这这里就主要是判断1的个数了);
    运用到的方法主要就是两次遍历数组,一次从前交往后,一次从后往前,

以下附上我的ac代码:

package 登;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;

public class D_1 {
	static int n;
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		
		BufferedReader sc=new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
		n=Integer.parseInt(sc.readLine());
		String s=sc.readLine();
		String[] ss=s.split(" ");
		int[] ch=new int[n];
		int[] test=new int[n];
		for(int i=0;i<n;i++) {
			ch[i]=Integer.parseInt(ss[i]);
			if(ch[i]!=1) {
				test[i]=0;
			}
			else {
				test[i]=1;
			}
		}
		if(n==1) {
			System.out.println("First");
			return;
		}
		for(int i=(n-1);i>0;i--) {
			if(ch[i-1]==1) {
				if(ch[i]==1) {
					test[i-1]=test[i]+1;
				}else {
					test[i-1]=1;
				}
			}else {
				test[i-1]=0;
			}
			
		}
		if(test[0]==n) {
			Arrays.fill(test, n);
		}else {
			if(test[0]!=0&&test[n-1]!=0) {
				test[n-1]=test[0]+1;
				for(int i=n-2;i>=0;i--) {
					if(test[i]==0)
						break;
					else {
						test[i]=test[i+1]+1;
					}
				}
			}
		}
		for(int i=0;i<n;i++) {
			if(test[i]%2==0&&test[i]!=n) {
				out.println("First");
			}else if(test[i]%2==0&&test[i]==n) {
				out.println("Second");
			}else if(test[i]%2!=0&&test[i]!=n) {
				out.println("Second");
			}else if(test[i]%2!=0&&test[i]==n) {
				out.println("First");
			}
		}
		out.flush();
		out.close();

	}


}

为了便于大家的理解,附上我的另一组代码,虽然没有ac,但思路是正确的就是有点超时:

package 登;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class D_2 {
	static int n;
	public static void main(String[] args) throws NumberFormatException, IOException {
		// TODO Auto-generated method stub
		
		BufferedReader sc=new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
		n=Integer.parseInt(sc.readLine());
		String s=sc.readLine();
		String[] ss=s.split(" ");
		int[] ch=new int[n];
		for(int i=0;i<n;i++) {
			ch[i]=Integer.parseInt(ss[i]);
		}
		for(int i=0;i<n;i++) {
			int m=countOne(ch,i);
			if(m%2==0&&m!=n) {
				out.println("First");
			}else if(m%2==0&&m==n) {
				out.println("Second");
			}else if(m%2!=0&&m!=n) {
				out.println("Second");
			}else if(m%2!=0&&m==n) {
				out.println("First");
			}
		}
		out.flush();
		out.close();

	}

	private static int countOne(int[] ch, int i) {
		// TODO Auto-generated method stub
		int count=0;
		if(ch[i]!=1)return count;
		else {
			while(ch[i]==1) {
				if(count==n) {
					break;
				}
				count++;
				i++;
				if(i==n) {
					i=0;
				}
			}
			return count;
		}
		
	}

}


http://www.niftyadmin.cn/n/1437175.html

相关文章

两种不同的ReadLine方法实例

本文部分内容摘抄自官网。 正解冒泡排序原理和过程 https://blog.csdn.net/number1killer/article/details/79032636 用python打印三角形和阶梯 https://blog.csdn.net/number1killer/article/details/78207842 程序算法之逆推法&#xff08;猴子摘桃问题正解&#xff09; …

mysql命令行导入导出sql文件

mysql命令行导入导出sql文件 以下来源于网上其他人的博客&#xff0c;做一下笔记 导出数据库用mysqldump命令&#xff08;注意mysql的安装路径&#xff0c;即此命令的路径&#xff09;&#xff1a; 首先进入到mysql安装目录下的bin中&#xff0c;比如说&#xff0c;我的安装目…

If和while语句的异同点实例解析

本文部分内容摘抄自书籍。 与while循环语句不同&#xff0c;即使在if语句中添加更新变量值的代码&#xff0c;if语句也不会自己进行循环。 将导致控制台窗口在“空白”中死循环。 用python和java打印乘法口诀的区别 https://blog.csdn.net/number1killer/article/details/7…

N皇后问题 ——Java

N皇后问题 ——Java 在N*N的方格棋盘放置了N个皇后&#xff0c;使得它们不相互攻击&#xff08;即任意2个皇后不允许处在同一排&#xff0c;同一列&#xff0c;也不允许处在与棋盘边框成45角的斜线上。 你的任务是&#xff0c;对于给定的N&#xff0c;求出有多少种合法的放置方…

C#while循环和for循环的工作原理分析

If和while语句的异同点 https://blog.csdn.net/number1killer/article/details/79761257 正解for循环运行步骤细节剖析&#xff08;那些你所不知道的细节&#xff09; https://blog.csdn.net/number1killer/article/details/78973866

JVM知识点汇总(1)

目录 一. Java 类加载过程 二. 描述一下 JVM 加载 Class 文件的原理机制 三 Java 内存分配 一. Java 类加载过程 Java 类加载需要经历以下 7 个过程 1. 加载 加载是类加载的第一个过程, 在这个阶段, 将完成以下三件事情: 通过一个类的全限定名获取该类的二进制流将该二进…

洛谷 P1219 八皇后问题——java dfs

洛谷 P1219 八皇后问题 题目描述 检查一个如下的6 x 6的跳棋棋盘&#xff0c;有六个棋子被放置在棋盘上&#xff0c;使得每行、每列有且只有一个&#xff0c;每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。 上面的布局可以用序列2 4 6 1 3 5来描述&#xff0c;第…

C#中for循环添加多个布尔式、多个布尔式中指定一个布尔式等等

while语句的特殊作用 https://blog.csdn.net/number1killer/article/details/79771247