1. 程式人生 > >20161215:數字拼接問題,DFS暴力搜尋

20161215:數字拼接問題,DFS暴力搜尋

題目:

         給出N個數組(2<=N<=9),每個數字長度是2-6位,每一位是1-4。如果某個數字尾數和其他的數頭相同,即可拼接成一個新的 數字。如:123,234 可以拼接成1234。

        連線成的新數字可以和其他未使用過的數字再按照規則連線成為新的數字。如:123,141,234可以連線成1234,14123和141234

        注:case裡面可能只有一部分數字可以連線:222 222可以形成22222,也可以形成2222

        求:能夠連線成的最大數字是幾位。

case:

5
3
123
141
234
2
24
123
4
343
2433
2213
3333
8
434121
441
4234
223142
23413
14342
224
234
9
221111
212111
122111
121232
211112
122112
211111
211121
121122

---------------------------------------------------------

import java.util.Scanner;

public class Test {
	// 拼接成的數字的最大長度
	static int maxLen = 0;

	public static void main(String[] args) {
		// long start = System.currentTimeMillis();
		// 將case輸入
		// Scanner in = new Scanner(new
		// FileInputStream("C:\\Users\\john\\Desktop\\sumsung_test\\Test30_1215_zhenti.txt"));
		Scanner in = new Scanner(System.in);
		// case的個數
		int CN = in.nextInt();
		int allcase[][] = new int[CN][];
		for (int j = 0; j < CN; j++) {
			int len = in.nextInt();
			int perdata[] = new int[len];
			for (int i = 0; i < perdata.length; i++) {
				perdata[i] = in.nextInt();
			}
			allcase[j] = perdata;
		}
		// for迴圈遍歷每個case
		for (int i = 0; i < allcase.length; i++) {
			// 每次case都初始化maxLen的值
			maxLen = 0;
			// 新建一維陣列存放case
			int[] data = allcase[i];
			// 呼叫函式
			DFS(data, 0, data.length - 1);
			// 輸出結果
			System.out.println(maxLen);

		}
		// long end = System.currentTimeMillis();
		// 程式執行時間
		// System.out.println((end - start) + "MS");
	}

	// 用遞迴全排列陣列的順序
	public static void DFS(int[] data, int start, int end) {
		// 迭代結束條件
		if (start == end) {
			// 插入函式:(每排列出一種組合就呼叫函式)依次進行拼接
			int nowlen = toMosaic(data);
			// 更新maxLen的值
			if (nowlen > maxLen) {
				maxLen = nowlen;
			}

		} else {
			// 陣列內元素進行組合的全排列(套路)
			for (int i = start; i <= end; i++) {
				int temp = data[start];
				data[start] = data[i];
				data[i] = temp;
				// 進行迭代
				DFS(data, start + 1, end);
				// 將陣列還原
				temp = data[start];
				data[start] = data[i];
				data[i] = temp;
			}

		}
	}

	// 將data陣列中的元素從前到後一次進行拼接
	public static int toMosaic(int[] data) {
		// 表示目前拼接成的長度
		int numLength = 0;
		// 遍歷陣列
		for (int i = 0; i < data.length - 1; i++) {
			// 標誌位,該值為0表示不能進行拼接
			int temp = 0;
			// 將陣列元素進行處理,方便拼接
			int[] data1 = numToArr(data[i]);
			int[] data2 = numToArr(data[i + 1]);
			int[] tail = tailArr(data1);
			int[] head = headArr(data2);
			// 一次比較頭陣列和尾陣列,看能否進行拼接
			for (int n = 0; n < tail.length && n < head.length; n++) {
				// 如果可以進行拼接
				if (tail[n] == head[n]) {
					if (i == 0) {
						// 第一個元素和第二個元素進行拼接的長度計算方法
						numLength = numLength + (n + 1) + (tail.length - 1 - n) + (head.length - 1 - n);
					} else {
						// 其他元素拼接的長度拼接方法
						numLength = numLength + (head.length - 1 - n);
					}
					// 將標誌位置1, 表示可以進行拼接
					temp = 1;
					break;// 直接break掉,因為已經是最大的長度
				}
			}
			// 如果不能拼接
			if (temp == 0 && i == 0) {
				return data1.length;// 第一個元素和第二個元素不能進行拼接
			} else if (temp == 0 && i != 0) {
				return numLength;// 其他情況
			}
		}
		// 如果全部可以拼接,返回長度
		return numLength;

	}

	// 獲取頭數-陣列
	public static int[] headArr(int[] data2) {
		int[] head = new int[data2.length];
		int sum = 0;
		for (int i = 0; i < data2.length; i++) {
			head[i] = sum * 10 + data2[i];
			sum = head[i];
		}
		return head;
	}

	// 獲取尾數-陣列
	public static int[] tailArr(int[] data1) {
		int[] tail = new int[data1.length];
		int ind = 0;
		int minus = 10;
		int sum = data1[data1.length - 1];
		for (int i = data1.length - 1; i >= 0; i--) {
			if (i == data1.length - 1) {
				tail[ind++] = data1[i];
			} else {
				tail[ind++] = data1[i] * minus + sum;
				sum = tail[ind - 1];
				minus *= 10;
			}
		}
		return tail;
	}

	// 將一個十進位制數轉換成為一維陣列
	public static int[] numToArr(int num) {
		int[] arr;
		int count = 0;
		int temp = num;
		while (temp != 0) {
			temp = temp / 10;
			count++;
		}
		arr = new int[count];
		for (int i = arr.length - 1; i >= 0; i--) {
			arr[i] = num % 10;
			num = num / 10;
		}
		return arr;
	}
}