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;
}

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