MarblesRegroupingHard [url]http://www.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm387[/url]
抽象问题:bigraph mincost
c1 c2 c3
box 1 = 140 90 63
box 2 = 73 142 70
box 3 = 79 142 7
bigraph可以抽象成矩阵问题,求最小流(要求每[color=red]列要用一次并且仅此一次[/color],行数>=列数)
上图的最小流如图所示:
c1 c2 c3
box 1 = 140 [color=red]90[/color] 63
box 2 = [color=red]73[/color] 142 70
box 3 = 79 142 [color=red]7[/color]
转为dp问题:
从box3--->box2---->box1看, box3的求值取决于box2(box2取决于box1,[color=red]递归求解[/color]),(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开始的
抽象问题:bigraph mincost
c1 c2 c3
box 1 = 140 90 63
box 2 = 73 142 70
box 3 = 79 142 7
bigraph可以抽象成矩阵问题,求最小流(要求每[color=red]列要用一次并且仅此一次[/color],行数>=列数)
上图的最小流如图所示:
c1 c2 c3
box 1 = 140 [color=red]90[/color] 63
box 2 = [color=red]73[/color] 142 70
box 3 = 79 142 [color=red]7[/color]
转为dp问题:
从box3--->box2---->box1看, box3的求值取决于box2(box2取决于box1,[color=red]递归求解[/color]),(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);
}
}