【洛谷OJ】【JAVA】P1149 火柴棒等式

36 篇文章 0 订阅

大部分人都是倒着写的,按数字倒推需要多少个火柴,然后计算火柴数量,如果火柴数量多一些的话,遍历起来就比较费劲了。

我的思路是正着计算,用两个for循环,通过遍历把火柴分成3份,每一份火柴计算出可能组成的数字序列,然后通过3个for循环遍历这些数字进行等式匹配,结合记忆搜索进行剪枝

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
	private static Scanner cin;
	private static LinkedList<Integer>[] list;
	private static HashMap equationCalced;
	private static HashMap calculatedN;
	public static void init() {
		list=new LinkedList[6];
		list[0] = new LinkedList<Integer>();
		list[0].add(1);//2 match can represent 1 
		list[1] = new LinkedList<Integer>();
		list[1].add(7);//3 match can represent 7
		list[2] = new LinkedList<Integer>();
		list[2].add(4);//4 match can represent 4
		list[3] = new LinkedList<Integer>();
		list[3].add(2);//5 match can represent 2
		list[3].add(3);//5 match can represent 3
		list[3].add(5);//5 match can represent 5
		list[4] = new LinkedList<Integer>();
		list[4].add(0);//6 match can represent 0
		list[4].add(6);//6 match can represent 6
		list[4].add(9);//6 match can represent 9
		list[5] = new LinkedList<Integer>();
		list[5].add(8);//7 match can represent 8
		
		equationCalced = new HashMap();
		calculatedN = new HashMap();
	}
	
	public static void main(String args[]) throws Exception {
		cin = new Scanner(System.in);
		int n = cin.nextInt();
		Main.init();
		int matchesForDigit = n-4;
		//we need at least 12 matches, the equation is 1+1=2
		if(n<13) {
			System.out.println(0);
		}else {
			System.out.println(calc(matchesForDigit));
		}
	}
	
	//calc digit which can be represented by n matches
	public static int calc(int n) {
		//LinkedList<Integer> digitList = new LinkedList<Integer>();
		int ret = 0;
		//get the first digit
		for(int i=2;i<=n-4;i++) {
			LinkedList<String> listA = digitWithMatchN(i);
			if(null == listA) {
				continue;
			}
			
			for(int j=2;j<=n-i-2;j++) {
				LinkedList<String> listB = digitWithMatchN(j);
				LinkedList<String> listC = digitWithMatchN(n-i-j);
				if (null == listB || null == listC) {
					continue;
				}
				Object[] arrayA = listA.toArray();
				Object[] arrayB = listB.toArray();
				Object[] arrayC = listC.toArray();
				for(int x=0;x<arrayA.length;x++) {
					for(int y=0;y<arrayB.length;y++) {
						for(int z=0;z<arrayC.length;z++) {
							long a = Long.valueOf((String)arrayA[x]);
							long b = Long.valueOf((String)arrayB[y]);
							long c = Long.valueOf((String)arrayC[z]);
							if(a + b == c) {
								if (equationCalced.containsKey(String.format("%d+%d", a,b))) {
									continue;
								}else {
									ret++;
									equationCalced.put(String.format("%d+%d", a,b), c);
								}
							}
						}
					}
				}
			}
		}
		return ret;
	}
	
	public static LinkedList<String> digitWithMatchN(int n) {
		if(calculatedN.containsKey(n)) {
			return (LinkedList<String>)calculatedN.get(n);
		}
		LinkedList<String> retList = new LinkedList<String>();
		if(n == 0) {
			return null;
		}else if(n==1) {
			//this match list can not present the right digit
			return null;
		}else if(n == 2){
			//return digit 1
			retList.add("1");
		}else if(n == 3) {
			//return digit 7
			retList.add("7");
		}else {
			for(int i=2;i<=7 && i<=n;i++) {
				Iterator<Integer> ai = list[i-2].iterator();
				//iterate digit in list[i-2]
				if(0 == n-i) {
					while(ai.hasNext()) {
						String tmpStr = String.valueOf(ai.next());
						retList.add(tmpStr);
					}
				}else {
					LinkedList<String> tmp = digitWithMatchN(n-i);
					if(null == tmp) {// n-1 match can not represent the right digit
						continue;
					}
					while(ai.hasNext()) {
						String tmpStr = String.valueOf(ai.next());
						Iterator tmpIt = tmp.iterator();
						boolean hasNext = false;
						while (tmpIt.hasNext()) {
							hasNext = true;
							String tmpStr2 = (String)tmpIt.next();
							if(tmpStr.equals("0")) {
								break;//if the prefix is 0, this digit is not illegal
							}else {
								retList.add(tmpStr +tmpStr2);
							}
						}
						if (!hasNext) {
							retList.add(tmpStr);
						}
					}
				}
			}
		}
		if(!calculatedN.containsKey(n)) {
			calculatedN.put(n, retList);
		}
		return retList;
	}
}
 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值