takapt0226's diary

競技プログラミングのことを書きます

POJ 3666 Making the Grade

解法

aを昇順にするコストをdpで求める。

hはaを昇順にsortしたものとする
dp[i + 1][j] = iをh[j]としたときの最小コスト
iをh[j]とするためには、i - 1はh[k] (k <= j)である必要があるので、以下のようなdpを解けばよい
dp[i + 1][j] = min{dp[i][k] (k <= j)} + | a[i] - h[j] |

aを降順にするコストはaを反転して同じ処理を使うと楽

ソースコード

int min_ascending(const vector<int>& a, const vector<int>& h)
{
    const int n = a.size();
    const int inf = INT_MAX;
    static int dp[2048][2048];	// (pos, height)
    erep(i, n) rep(j, n)
	dp[i][j] = inf;

    dp[0][0] = 0;
    rep(i, n)
    {
	int min_cost = inf; // min{dp[i][k]; k <= j}
	rep(j, n)
	{
	    chmin(min_cost, dp[i][j]);
	    dp[i + 1][j] = min_cost + abs(a[i] - h[j]);
	}
    }

    int res = inf;
    rep(j, n)
	chmin(res, dp[n][j]);
    return res;
}
int main()
{
    int n;
    scanf("%d", &n);
    vector<int> a(n);
    rep(i, n)
	scanf("%d", &a[i]);
    vector<int> h = a;
    sort(all(h));

    int res = min_ascending(a, h);
    reverse(all(a));
    chmin(res, min_ascending(a, h));
    printf("%d\n", res);
}