您的位置:首页 > 其它

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

2014-08-06 22:03 351 查看
     博弈论中几个简单的题目

     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代表必胜态,则

OOOOOO
XOXOXO
OOOOOO
XOXOXO
OOOOOO
XOXOXO
    这样就能轻易的得出答案
    代码如下:/*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");
else
out.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);
else
out.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
;
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: