POJ 1991 Turning in Homework(區間DP)
阿新 • • 發佈:2017-09-09
clu sin highlight sort stream ret spa 作業 ref
題目鏈接 Turning in Homework
考慮區間DP
f[i][j][0]為只考慮區間[i, j]且最後在a[i]位置交作業的答案。
f[i][j][1]為只考慮區間[i, j]且最後在a[j]位置交作業的答案。
首先對a[i]升序排序(位置第一關鍵字,時間第二關鍵字)
然後就是區間DP了
f[i][j]可以從f[i][j + 1], f[i - 1][j]推過來。
即
f[i][j][0] = min(f[i][j][0], max(f[i][j + 1][1] + a[j + 1].fi - a[i].fi, a[i].se))
f[i][j][0] = min(f[i][j][0], max(f[i - 1][j][0] + a[i].fi - a[i - 1].fi, a[i].se))
f[i][j][1] = min(f[i][j][1], max(f[i - 1][j][0] + a[j].fi - a[i - 1].fi, a[j].se));
f[i][j][1] = min(f[i][j][1], max(f[i][j + 1][1] + a[j + 1].fi - a[j].fi, a[j].se));
其中fi代表位置,se代表時間。
最後的答案為min{min(f[i][i][0], f[i][i][1]) + abs(a[i].fi - B)}
B位規定的終點。
時間復雜度$O(n^{2})$
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 1010; int n, m, ed, ans; pair <int, int> a[N]; int f[N][N][2]; int main(){ scanf("%d%d%d", &n, &m, &ed); rep(i, 1, n) scanf("%d%d", &a[i].fi, &a[i].se); sort(a + 1, a + n + 1); f[1][n][0] = max(a[1].fi, a[1].se); f[1][n][1] = max(a[n].fi, a[n].se); dec(d, n - 1, 1){ rep(i, 1, n - d + 1){ int j = i + d - 1; f[i][j][0] = 1 << 30; if (j < n) f[i][j][0] = min(f[i][j][0], max(f[i][j + 1][1] + a[j + 1].fi - a[i].fi, a[i].se)); if (i > 1) f[i][j][0] = min(f[i][j][0], max(f[i - 1][j][0] + a[i].fi - a[i - 1].fi, a[i].se)); f[i][j][1] = 1 << 30; if (i > 1) f[i][j][1] = min(f[i][j][1], max(f[i - 1][j][0] + a[j].fi - a[i - 1].fi, a[j].se)); if (j < n) f[i][j][1] = min(f[i][j][1], max(f[i][j + 1][1] + a[j + 1].fi - a[j].fi, a[j].se)); } } ans = 1 << 30; rep(i, 1, n) ans = min(ans, min(f[i][i][0], f[i][i][1]) + abs(a[i].fi - ed)); printf("%d\n", ans); return 0; }
POJ 1991 Turning in Homework(區間DP)