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

再啟動發表於2018-08-26

大部分人都是倒著寫的,按數字倒推需要多少個火柴,然後計算火柴數量,如果火柴數量多一些的話,遍歷起來就比較費勁了。

我的思路是正著計算,用兩個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;
	}
}