UVA 1025 A Spy in the Metro(DP)

題目鏈接

有N個地鐵站,每個地鐵站之間的行駛是雙向的,並且需要的時間也是固定的,然後又m1列火車在不同的時段從左側發出,有m2列火車在不同的時段從右側發出, 現在問你經過T時間後,到達站點n過程中一共在站臺等待的時間的最小值是多少。

預處理出在第 i 時間 j 站臺經過經過多少時間到達 j+1 和 j-1 的 l 和 r 數組,刷表法,開始進行狀態轉移,dp[i][j]表示在第i時間第j站臺的最小值,那麼先把他們全都賦爲INF,dp[0][1]即開始位置是0,設這個時間這個站臺剛好有向右的地鐵耗時爲t, 那麼 dp[i+t][j+1] = min(dp[i+t][j+1], dp[i][j]) (i+t <= T && j+1 <= N) ,往左同理,別忘了還有不坐地鐵的情況,如果當前的狀態可以到達,就dp[i+1][j] = min(dp[i+1][j], dp[i][j])。
最後判斷dp[T][N]是否是INF就行,如果是的話就說明無法轉移到這個狀態,輸出impossible,否則輸出dp[T][N]。
動態規劃題目的寫法多的不得了,不是看了別人的題解就一定要怎麼怎麼寫,比如這題還可以從n站臺往1站臺轉移。重要的是思路,也就是狀態轉移。
判斷是否是合法轉移的時候一定要多想想,小心數組越界!

#include <bits/stdc++.h>

using namespace std;

const int INF = 0x3f3f3f3f;
int N, T, t[210], l[210][60], r[210][60], dp[210][60];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif

    int kase = 1;
    while (cin >> N) {
        if (!N) break;
        cin >> T;
        for (int i = 1; i <= N-1; ++i) cin >> t[i];
        int m, x;
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        cin >> m;
        for (int i = 0; i < m; ++i) {
            cin >> x;
            int idx = 1, now = x;
            while (idx < N && now <= T) {
                r[now][idx] = t[idx];
                now += t[idx];
                ++idx;
            }
        }
        cin >> m;
        for (int i = 0; i < m; ++i) {
            cin >> x;
            int idx = N, now = x;
            while (idx > 1 && now <= T) {
                l[now][idx] = t[idx-1];
                now += t[idx-1];
                --idx;
            }
        }
        memset(dp, 0x3f, sizeof(dp));
        dp[0][1] = 0;
        for (int i = 0; i < T; ++i) {
            for (int j = 1; j <= N; ++j) {
                if (dp[i][j] != INF) dp[i+1][j] = min(dp[i+1][j], dp[i][j] + 1);
                int temp = r[i][j];
                if (j < N && temp && i + temp <= T) dp[i+temp][j+1] = min(dp[i+temp][j+1], dp[i][j]);
                temp = l[i][j];
                if (j > 1 && temp && i + temp <= T) dp[i+temp][j-1] = min(dp[i+temp][j-1], dp[i][j]);
            }
        }
        cout << "Case Number "<< kase++ << ": ";
        if (dp[T][N] == INF) cout << "impossible" << '\n';
        else cout << dp[T][N] << '\n';
    }


#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章