Skip to content

Instantly share code, notes, and snippets.

@amoshyc
Last active August 29, 2015 14:15
Show Gist options
  • Save amoshyc/03d0b3f62b3cd2f63d2e to your computer and use it in GitHub Desktop.
Save amoshyc/03d0b3f62b3cd2f63d2e to your computer and use it in GitHub Desktop.
Bribe the Prisoners(GCJ 2009 Round 1C)

#Bribe the Prisoners(GCJ 2009 Round 1C)

題目

DP。

像無界背包問題一樣,引入 區間 性質。

position[] 記錄囚犯的位置。 (a, b) 為開區間。 dp(a, b) 為釋放第 a+1 個第 b-1 個 囚犯所需的最少金幣,則

dp(a, b) 
= min([dp(a, c) + dp(c, b) for all c such that a < c < b]) + 		  
  cost to release current prisoner(c)

where cost to release current prisoner(c)
= (position[b]-1) - (position[a]+1) + 1 - 1

DP 的初使條件,因 (a, b) 是開區間,所以

dp(i, i+1) = 0

為實作方便,另外假設有兩個囚犯分別在通道的頭跟尾。

position[0] = 0;
position[Q+1] = P+1;

結果便是:

dp(0, Q+1)

Code

採 Top-down 的方式來建 dp。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>

using namespace std;

int dp[100+2][100+2];
int pos[100+2];

int solve(int left, int right) {
    if (dp[left][right] != -1)
        return dp[left][right];

    if (left + 1 == right)
        return dp[left][right] = 0;

    dp[left][right] = 10000000;
    for (int c = left+1; c < right; c++) {
        int value = solve(left, c) + solve(c, right) +
                    (pos[right]-1) - (pos[left]+1) +1 -1;
        dp[left][right] = min(dp[left][right], value);
    }

    return dp[left][right];
}

int main() {
    int N;
    cin >> N;

    for (int case_ = 1; case_ <= N; case_++) {
        memset(dp, -1, sizeof(dp));
        memset(pos, -1, sizeof(pos));

        int P, Q;
        cin >> P >> Q;

        pos[0] = 0;
        for (int i=1; i<=Q; i++)
            cin >> pos[i];
        pos[Q+1] = P+1;

        cout << "Case #" << case_ << ": " << solve(0, Q+1) << endl;
    }

    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment