华为机试题--24点游戏--In Java

题目描述

问题描述:给出4个1-10的数字,通过加减乘除,得到数字为24就算胜利
输入:
4个1-10的数字。[数字允许重复,测试用例保证无异常数字]
输出:
true or false


这个问题首先能够想到的做法就是暴力枚举,但是这样的话情况太多,写的也太麻烦了点。

所以用递归的方法来做是很方便的。但是要注意到的是,所给的4个数字的运算顺序并不一定是输入的顺序,而且加括号也是允许的。所以我的解决方法是,对4个数字进行全排列,对操作符的选择进行递归,这样不怕找不出一种合适的情况来。找到第一种正确情况时,打印并结束程序,没找到的话,打印false并结束程序。

为了考虑到加括号的情况,递归中有两种步长选择,一种是一步,一种是两步,说白了就是在当前的结果上再加减乘除一个还是两个数,如果是两个数的话,不就相当于它们两先在括号中运算好,再和当前值相运算吗?

dfs方法中m表示当前值,i代表当前操作数的角标,tc是输入4个数的一种全排列。

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;


public class Main{
	public static int[] nu;
	
	public static boolean dfs(Integer[] tc,int i,int m){
		if(i>=4){
			if(m==24){
				//System.out.println(Arrays.toString(tc));
				return true;
			}else{
				return false;
			}
		}
		
		if(i+1<4){
			int tem1 = tc[i];
			int tem2 = tc[i+1];
			return
			dfs(tc,i+2,m+(tem1+tem2))||
			dfs(tc,i+2,m+(tem1-tem2))||
			dfs(tc,i+2,m+(tem1*tem2))||
			(tem2!=0 && dfs(tc,i+2,m+(tem1/tem2)))||
			
			dfs(tc,i+2,m-(tem1+tem2))||
			dfs(tc,i+2,m-(tem1-tem2))||
			dfs(tc,i+2,m-(tem1*tem2))||
			(tem2!=0 && dfs(tc,i+2,m-(tem1/tem2)))||
			
			dfs(tc,i+2,m*(tem1+tem2))||
			dfs(tc,i+2,m*(tem1-tem2))||
			dfs(tc,i+2,m*(tem1*tem2))||
			(tem2!=0 && dfs(tc,i+2,m*(tem1/tem2)))||
			(tem1+tem2!=0 && dfs(tc,i+2,m/(tem1+tem2)))
			||(tem1-tem2!=0 && dfs(tc,i+2,m/(tem1-tem2)))
			||(tem1*tem2!=0 && dfs(tc,i+2,m/(tem1*tem2)))
			||(tem1/tem2!=0 && dfs(tc,i+2,m/(tem1/tem2)))
			||
	
			
			dfs(tc,i+1,m+tc[i])||
			dfs(tc,i+1,m-tc[i])||
			dfs(tc,i+1,m*tc[i])||
			(tc[i]!=0 && m%tc[i]==0 &&dfs(tc,i+1,m/tc[i]));
		}else{
			return
					dfs(tc,i+1,m+tc[i])||
					dfs(tc,i+1,m-tc[i])||
					dfs(tc,i+1,m*tc[i])||
					(tc[i]!=0&& m%tc[i]==0 && dfs(tc,i+1,m/tc[i]));	
		}
			
		
		
		
	}
	
	
	public static List<List<Integer>> permute(int[] nums) {
        int N= nums.length;
        List<List<Integer>> re = new ArrayList();
        if(N==1){
        	List a = new ArrayList();
        	a.add(nums[0]);
        	re.add(a);
        	return re;
        }
        
        int[] annums = new int[N-1];
        int la = nums[N-1];
        for(int i=0;i<N-1;i++){
        	annums[i] = nums[i];
        }
        for(int i=0;i<N;i++){
        	for(List<Integer> tt : permute(annums)){
        		tt.add(i, la);
        		re.add(tt);
        	}
        }
        return re;
    }
	
	
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		
		while(sc.hasNext()){
			boolean flag = false;
			String raw = sc.nextLine();
			String[] a = raw.split(" ");
			nu = new int[4];
			for(int i=0;i<4;i++){
				nu[i] = Integer.valueOf(a[i]);
			}
			List re = permute(nu);
			int N = re.size();
			for(int i=0;i<N;i++){
				List<Integer> c = (List) re.get(i);
				Integer[] tc = new Integer[4];
				c.toArray(tc);
				//System.out.println(Arrays.toString(tc));
				if(dfs(tc,0,0)==true){
					System.out.println(true);
					flag = true;
					break;
				}
			}
			//System.out.println(dfs(new Integer[]{10,2,5,1},0,0));
			if(flag == false)
				System.out.println(false);
		}
	} 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值