前言:在编程问题中,取球游戏的一般解题模板
伪代码:
f(局面x){//——>胜(true)负(false)
边界条件处理。。。。。
For(我所有可能的走法){
试着走一步——>局面y
胜负t = f(y);
If(t==负)return 胜;
回溯,恢复局面
}
return 负;
}
一、取球游戏
今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,
也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断。
我们约定:
每个人从盒子中取出的球的数目必须是:1,3,7或者8个。
轮到某一方取球时不能弃权!
A先取球,然后双方交替取球,直到取完。
被迫拿到最后一个球的一方为负方(输方)
请编程确定出在双方都不判断失误的情况下,对于特定的初始球数,A是否能赢?
程序运行时,从标准输入获得数据,其格式如下:
先是一个整数n(n<100),表示接下来有n个整数。然后是n个整数,每个占一行(整数<10000),表示初始球数。程序则输出n行,表示A的输赢情况(输为0,赢为1)。
例如,用户输入:
4
1
2
10
18
则程序应该输出:
1
1
代码:
publicclass 取球游戏 {
public static boolean f(int n){
if(n >= 1 &&f(n-1) == false ) return true;
if(n >=3 &&f(n-3) == false ) return true;
if(n >=7 &&f(n-7) == false ) return true;
if(n >=8 &&f(n-8) == false ) return true;
return false;
}
public static void main(String[] args){
System.out.println(f(10));//测试10个球
}
}
这个代码写的还是,不错的。通俗易懂,写的又漂亮!但是当球很多的时候,会超时有木有!!!
上面的算法:添加时间
import Java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
long begin = System.currentTimeMillis();
int a[] = {1,3,7,8};
Scanner sc = new Scanner(System.in);
int b = sc.nextInt();
System.out.println(f(a , b));//测试10个球
long end = System.currentTimeMillis();
System.out.println("运行时间是:"+(end-begin)/1000.0f);
}
public static boolean f(int a[], int n){
for(int i = 0 ; i < a.length ; i++){
if(n >= a[i] && f(a , n-a[i])==false ){
return true;
}
}
return false;
}
}
当输入的数为55 的时候,需要运行6s多,输入60时10s都出不来;这个是让人无法忍受的;
好了:下面用动态规划求解
import java.util.Scanner;
public class test {
static int it[] = new int[1000] ;//用一个数组来保持中间结果
public static void main(String[] args) {
int c[] = {1,3,7,8};
Scanner sc = new Scanner(System.in);
int b = sc.nextInt();
System.out.println(f(c , b));//测试10个球
}
//false == -1 ; true == 1 ; 0 --> 没有初始化;
public static int f(int a[] , int n){
if(it[n]!=0)return it[n];//如果在数组里面保存了这个值,马上返回
for(int i = 0 ; i < a.length ; i++){
if(n >= a[i] && f(a , n-a[i])==-1 ){
it[n] = 1;
return 1;
}
}
it[n] = -1;
return -1;
}
}
输入200 都很快出来了,再次体现了动态规划的优越性,有木有!
http://blog.csdn.net/u012535132/article/details/45253897