TakahiroNakamori

TakahiroNakamori

中森崇博(ナカモリタカヒロ)

12 /
22
2021
 

マーブル

問題

D – マーブル
プログラミング初級者から上級者まで楽しめる、競技プログラミングコンテストサイト「AtCoder」。オンラインで毎週開催プログラミングコンテストを開催しています。競技…

解法

コード例

#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
using ll = long long;
using P = pair<int, int>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
// using mint = modint998244353;
// using mint = modint1000000007;
// const int mod = 1000000007;
// const ll INF = 1LL << 60;
const int INF = 1001001001;

int R, G, B;

// マーブルを1移動させるのにコストは1必要。
// R,G,B <= 300 なので、いい感じに並べればは1000を超えることない
// 0 〜 1000 の 0 からRを置いていくとすると
// R のコストは 400(中央から-100) - 置いた位置
// G のコストは 500(中央) - 置いた位置
// B のコストは 600(中央から+100) - 置いた位置
// と言える。

int cost(int pos, int cnt) {
  if(G + B <= cnt) {
    // Rを置く
    return abs(400 - pos);
  } else if(B <= cnt) {
    // Gを置く
    return abs(500 - pos);
  } else {
    // Bを置く
    return abs(600 - pos);
  }
}

int main() {
  cin >> R >> G >> B;

  int sum = R + G + B;
  // dp[見ている箱][残りのマーブル]:= この状況になるための最小の移動数
  vector<vector<int>> dp(1000, vector<int>(sum + 1, INF));

  // マーブルを1個触っていないとき(残りマーブル = sum)は 0
  rep(i, 1000) { dp[i][sum] = 0; }

  // i番目にマーブルを置かなかった場合と、マーブルを置いた場合で小さい方を採用
  for(int i = 1; i < 1000; ++i) {
    rep(j, sum) { dp[i][j] = min(dp[i - 1][j], dp[i - 1][j + 1] + cost(i, j)); }
  }

  // 全パターンの最小値が答え
  int ans = INF;
  rep(i, 1000) { ans = min(ans, dp[i][0]); }

  cout << ans << endl;
  return 0;
}