1. 程式人生 > >lintcode最小調整代價

lintcode最小調整代價

題目:
給一個整數陣列,調整每個數的大小,使得相鄰的兩個數的差不大於一個給定的整數target,調整每個數的代價為調整前後的差的絕對值,求調整代價之和最小是多少。
假設陣列中每個整數都是正整數,且小於等於100。
樣例:
對於陣列[1, 4, 2, 3]和target=1,最小的調整方案是調整為[2, 3, 2, 3],調整代價之和是2。返回2。
解題思路:
欲使|A(i)-A(i+1)|<=target
則A(i+1)-target<=A(i)<=target+A(i+1)
又因為0<=A(n)<=100
所以max(0,A(i+1)-target)<=A(i)<=min(100,target+A(i+1))
由於題目中要求陣列A中每個數都小於等於100,所以我們可以構建一個(n,100)的矩陣Z,Z(i,j)表示A(i)調整為j的花費與A(i-1)調整為j-target<=A(i)<=target+j的最小花費之和。以樣例為例,首先構建一個矩陣Z如下:

0 1 2 3 4
1 1 0 1 2 3
4 4 3 2
2
3

其中Z(1,2)表示A(1)=4調整為1花費與A(0)=1調整為2-1至2+1的最小花費之和,也就是滿足題目要求的前兩個數的最小花費。
程式碼:

public int MinAdjustmentCost(List<Integer> A, int target) {
		int result = 0;
		int len = A.size();
		if(len <= 1) {
			return result;
		}
		int[][] cost = new int[len][100];
		for(int i=0;i<100;i++) {
			cost[0][i] =Math.abs(A.get(0)-i); 
		}
		for(int i=1;i<len;i++) {
			for(int j=0;j<100;j++) {
				int up = Math.min(99, j+target);
				int low = Math.max(0, j-target);
				int diff = Math.abs(A.get(i)-j);
				cost[i][j] = Integer.MAX_VALUE;  
                for (int k = low; k <= up; k++) {  
                    cost[i][j] = Math.min(cost[i][j], cost[i-1][k] + diff);  
                }
			}
		}
		result = Integer.MAX_VALUE;
		for(int i=0;i<100;i++) {
			result = Math.min(cost[len-1][i], result);
		}
		return result;
    }