Hatena::Grouptopcoder

tsubosakaの日記

2009-01-17

SRM 310 Div1 Hard

| 18:20

すでに使った箱の集合といちばん上の箱の状態をキーとしてDPする.箱の状態はどこをz軸にするかの3通り考えれば十分なのでキーの数は2^n * 3n でn <= 15より実行時間内に解ける.

public class BoxTower {
  public int tallestTower(int[] x, int[] y, int[] z) {
    int n = x.length;
    int dp[][] = new int[1 << n][3 * n];
    int ws[][] = new int[3 * n][2];
    int hs[] = new int[3 * n];
    for(int i = 0 ; i < n ; i++){
      dp[1 << i][i] = hs[i] = z[i];
      ws[i][0] = Math.min(x[i], y[i]);
      ws[i][1] = Math.max(x[i], y[i]);
      dp[1 << i][i + n] = hs[i + n] = y[i];
      ws[i + n][0] = Math.min(x[i], z[i]);
      ws[i + n][1] = Math.max(x[i], z[i]);
      dp[1 << i][i + 2 * n] = hs[i + 2 * n] = x[i];
      ws[i + 2 * n][0] = Math.min(y[i], z[i]);
      ws[i + 2 * n][1] = Math.max(y[i], z[i]);
    }
    for(int S = 0 ; S < dp.length ; S++){
      for(int j = 0 ; j < 3 * n; j++){
        int tj = j % n;
        if((S & (1 << tj)) == 0)continue;
        for(int k = 0 ; k < 3 * n ; k++){
          int tk = k % n;
          if(((S & (1 << tk))) != 0)continue;
          int next = (S | (1 << tk));
          if(ws[k][0] <= ws[j][0] && ws[k][1] <= ws[j][1])
            dp[next][k] = Math.max(dp[next][k], dp[S][j] + hs[k]);          
        }
      }
    }
    int res = 0;
    for(int d[] : dp){
      for(int i : d)res = Math.max(i, res);
    }
    return res;
  }
}