POJ 2348& HDU 2147&HDU 1846&POJ 1067&HDU 1850 简单的博弈

来源:互联网 发布:家庭健身器材 知乎 编辑:程序博客网 时间:2024/05/29 04:26

     博弈论中几个简单的题目

     POJ 2348

     若b已经是a的倍数,这就已经是必胜态,否则,若a>b,则交换a,b。若b-a<a,则就将在必胜态与必败态之间转化,若b-a>a则先手就可以用一步操作将其转变为b-a<a。

     代码如下:

/*author by *nightmare */import java.io.*;public class poj2348 {static int a;static int b;public static void main(String args[]) throws IOException {StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));while(true){in.nextToken();a = (int)in.nval;in.nextToken();b = (int)in.nval;if(a+b==0)break;boolean flag = true;while(true){if(a>b)swap();if(b%a==0)break;if(b-a>a)break;if(b-a<a){b-=a;flag = !flag;}}out.println(flag?"Stan wins":"Ollie wins");}out.flush();out.close();}public static void swap(){int tmp = a;a = b;b = tmp;}}

    HDU2147

    典型的巴什博奕P/N之间的转换

    首先,若棋盘只有一个格子,那就是必败态。

    那么能一步进入必败态的即是必胜态,相反则是必败态。

    那么我们可以从一个格子向外扩展开形成一个表格X代表必败态,O代表必胜态,则

OOOOOOXOXOXOOOOOOOXOXOXOOOOOOOXOXOXO    这样就能轻易的得出答案

    代码如下:

/*author by *nightmare */import java.io.*;public class poj2348 {static int a;static int b;public static void main(String args[]) throws IOException {StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));while(true){in.nextToken();a = (int)in.nval;in.nextToken();b = (int)in.nval;if(a+b==0)break;boolean flag = true;while(true){if(a>b)swap();if(b%a==0)break;if(b-a>a)break;if(b-a<a){b-=a;flag = !flag;}}out.println(flag?"Stan wins":"Ollie wins");}out.flush();out.close();}public static void swap(){int tmp = a;a = b;b = tmp;}}

    HDU 1846

    巴什博奕的裸题

    即n%(m+1)==0为先手必败。

    此题还可以改成最后一个拿的为败,则(n-1)%(m+1)==0先手必败

    代码如下:

/*author by *nightmare */import java.io.*;public class hdu1846 {public static void main(String args[]) throws IOException {StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));in.nextToken();int t = (int)in.nval;while(t-->0){in.nextToken();int n = (int)in.nval;in.nextToken();int k = (int)in.nval;if(n%(k+1)==0)out.println("second");elseout.println("first");}out.flush();out.close();}}

    POJ 1067

    威佐夫博奕的裸题,直接套公式即可

    ak = k(1+√5)/2,bk = ak+k;

    注意要记得强制转换。

    用了一下异或交换两个数值,感觉并没有swap()快。

    代码如下:

/*author by *nightmare */import java.io.*;public class poj1067 {public static void main(String args[]) throws IOException {StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));while (in.nextToken() != StreamTokenizer.TT_EOF) {int n = (int) in.nval;in.nextToken();int m = (int) in.nval;if (n < m) {n ^= m;m ^= n;n ^= m;}if (m ==(int)( (n - m) * (1 + Math.sqrt(5)) / 2))out.println(0);elseout.println(1);}out.flush();out.close();}}

    HDU 1850

    简单的NIM游戏,只是问的方法不一样而已,问有几种操作。

    若a1^a2^...^ak^...^an !=0 = k;

    则先手可用一步操作将其变为0;

    ak^k<ak,即ak还有k中最高位的那个1,找到所有的ak即可

    代码如下:

/*author by *nightmare */import java.io.*;public class hdu1850 {public static void main(String args[]) throws IOException {StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));while (true) {in.nextToken();int n = (int) in.nval;if (n == 0)break;int a[] = new int[n];int sum = 0;for (int i = 0; i < n; i++) {in.nextToken();a[i] = (int) in.nval;sum ^= a[i];}int ans = 0;for (int i = 0; i < n; i++) {if ((sum ^ a[i]) < a[i])ans++;}out.println(ans);}out.flush();out.close();}}


0 0