(dp)MarblesRegroupingHard --bigraph mincost

MarblesRegroupingHard http://www.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm387

抽象问题:bigraph mincost
         c1    c2    c3
box 1 = 140   90    63
box 2 = 73    142   70
box 3 = 79    142   7

bigraph可以抽象成矩阵问题,求最小流(要求每 列要用一次并且仅此一次,行数>=列数)
上图的最小流如图所示:
         c1    c2    c3
box 1 = 140   90    63
box 2 = 73    142   70
box 3 = 79    142   7

转为dp问题:
从box3--->box2---->box1看, box3的求值取决于box2(box2取决于box1, 递归求解),(box2求得值后+box3这一行的值),再比较即可得到最小值。看代码

链接中的题解opt(函数内)boxes应该是(total number of marles of color i) - boxes[j][i],即
         c1    c2    c3
box 1 = 140   90    63
box 2 = 73    142   70
box 3 = 79    142   7

而不是原来的boxes的值
opt(n, first m bits set to 1), n应该是numberOfColor-1,应为index是从0开始的


package srm387;

import java.util.Arrays;

public class MarblesRegroupingHard {
	int w[][];
	int dp[][] = new int[51][1 << 15];
	int numberColors;

	public int minMoves(String[] boxes) {
		for (int i = 0; i < dp.length; i++) {
			Arrays.fill(dp[i], -1);
		}
		String[] temp = boxes[0].split(" ");
		numberColors = temp.length;
		w = new int[boxes.length][numberColors];
		int[][] vals = new int[boxes.length][numberColors];
		for (int i = 0; i < boxes.length; i++) {
			String[] arr = boxes[i].split(" ");
			for (int j = 0; j < arr.length; j++) {
				//vals是原来的值,只是String的改为int的
				vals[i][j] = Integer.parseInt(arr[j]);
			}
		}

		//w是真正要求的bigraph流:(total number of marles of color i) - boxes[j][i]
		for (int i = 0; i < boxes.length; i++) {
			for (int j = 0; j < numberColors; j++) {
				for (int k = 0; k < boxes.length; k++) {
					if (k != i) {
						w[i][j] += vals[k][j];
					}
				}
			}
		}

		//index从boxes.length-1开始, (1 << numberColors) - 1代表有numberColors个位
		return opt(boxes.length - 1, (1 << numberColors) - 1);

	}

	//upto 是boxes的index,从numberColors-1到0, used代表还有多少颜色没赋到box里,used用bit思想
	public int opt(int upto, int used) {
		//如果越过0的边界到达-1
		if (upto == -1) {
			//如果颜色都已赋完,没有颜色赋给box,则返回0,已经ok,不需要cost.//否则此路不通,返回Max_value
			if (used == 0) {
				return 0;
			} else {
				return 1000000000;
			}
		}

		//如果已经计算过了,就不必要重新计算。这是memoization 的好处
		if (dp[upto][used] != -1) {
			return dp[upto][used];
		}

		//这个box不填颜色,直接赋给下一个index
		dp[upto][used] = opt(upto - 1, used);

		int t = 1000000000;
		for (int i = 0; i < numberColors; i++) {
			if ((used & 1 << i) != 0) {
				//clear used的第i位bit
				int used1 = used & ~(1 << i);
				//这个box填入颜色i,然后把第i位bit clear(因为第i位颜色已经在赋给了这个box),再传入下一个box
				t = w[upto][i] + opt(upto - 1, used1);
			}
			if (t == 1000000000) {
				continue;
			}
			if (dp[upto][used] > t) {
				dp[upto][used] = t;
			}
		}

		return dp[upto][used];
	}

	public static void main(String[] args) {
		MarblesRegroupingHard m = new MarblesRegroupingHard();
		String[] boxes = { "6 97 7", "73 45 0", "67 45 63" };
		int cost = m.minMoves(boxes);
		System.out.println(cost);
	}
}

你可能感兴趣的:(J#)