dp转移方程很容易想 dp[i][j] = min{dp[i - 1][k] + abs(pos[i][j] -pos[i - 1][j]) + cost[i][j]}
n行m列 每次转移扫描m次 共n*m*m 为O(10^7) 1500ms,可以暴力一试。姿势不对就会TLE
其实加上个内联函数求绝对值,同时赋值时候不使用min(a, b) 用G++交 就可以水过
正解是:因为每个转移都是从上一层所有的状态开始转移,将上一层的状态根据pos排序
对当前状态的pos进行讨论,其坐标轴左边的点dp[i][j] = dp[i - 1][k] - pos][i - 1][k]+ pos[i][j] + cost[i][j]
对其坐标轴右边的点便是 dp[i][j] = dp[i - 1][k]+ pos][i - 1][k] - pos[i][j] + cost[i][j], pos][i][j] 和 cost[i][j]是常数。
维护一个lans[i],表示上一层0 ~ i位置的dp[i - 1][k] - pos][i - 1][k]最小值; 和一个rans[i],表示上一层i ~ (m - 1)位置的dp[i - 1][k] + pos][i - 1][k]最小值
二分当前状态的pos,若为p,比较左边lans[p - 1]与右边lans[p]的最小值即可
//#pragma comment(linker, "/STACK:102400000,102400000") //HEAD #include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <algorithm> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <cstdlib> using namespace std; //LOOP #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FED(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) //STL #define PB push_back //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RS(s) scanf("%s", s) #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i) #define CPY(a, b) memcpy(a, b, sizeof(a)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) #define EQ(a, b) (fabs((a) - (b)) <= 1e-10) #define ALL(c) (c).begin(), (c).end() #define SZ(V) (int)V.size() #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p) #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q) #define WI(n) printf("%d\n", n) #define WS(s) printf("%s\n", s) #define sqr(x) x * x typedef long long LL; typedef vector <int> VI; typedef unsigned long long ULL; const double eps = 1e-10; const LL MOD = 1e9 + 7; using namespace std; const int maxn = 1010; const int INF = 0x3f3f3f3f; int dp[55][maxn], n, m, x; int lm[maxn], rm[maxn], lans[maxn], rans[maxn]; struct Node{ int pos, cost; int lval, rval; bool operator <(const Node& a) const { return pos < a.pos; } }a[55][maxn]; void init(int u) { REP(j, m) { a[u][j].lval = dp[u][j] - a[u][j].pos; a[u][j].rval = dp[u][j] + a[u][j].pos; } sort(a[u], a[u] + m); CLR(lm, INF), CLR(rm, INF); int s = 0, e = 0; lans[0] = lm[0] = a[u][0].lval, rans[m - 1] = rm[0] = a[u][m - 1].rval; FF(j, 1, m) { Node &v = a[u][j]; if (v.lval > lm[e]) lm[++e] = v.lval; else { while (e >= 0 && v.lval < lm[e]) --e; lm[++e] = v.lval; } lans[j] = lm[0]; } s = e = 0; FED(j, m - 2, 0) { Node &v = a[u][j]; if (v.rval > rm[e]) rm[++e] = v.rval; else { while (e >= 0 && v.rval < rm[e]) --e; rm[++e] = v.rval; } rans[j] = rm[0]; } } int main() { int T; RI(T); while (T--) { RIII(n, m, x); REP(i, n) REP(j, m) RI(a[i][j].pos); REP(i, n) REP(j, m) RI(a[i][j].cost); REP(j, m) dp[0][j] = abs(x - a[0][j].pos) + a[0][j].cost; FE(i, 1, n - 1) { init(i - 1); REP(j, m) { int p = lower_bound(a[i - 1], a[i - 1] + m, a[i][j]) - a[i - 1]; // cout << "position "<< p << endl; int lmin = INF, rmin = INF; if (p) lmin = lans[p - 1] + a[i][j].pos + a[i][j].cost; if (p < m) rmin = rans[p] - a[i][j].pos + a[i][j].cost; // cout << "rans[p]: " << rans[p] << endl; // cout << "lmin: " <<lmin << "rmin: " << rmin << endl; dp[i][j] = min(lmin, rmin); } } int ans = INF; REP(j, m) ans = min(dp[n - 1][j], ans); cout << ans << endl; } return 0; }
//#pragma comment(linker, "/STACK:102400000,102400000") //HEAD #include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <algorithm> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <cstdlib> using namespace std; //LOOP #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FED(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) //STL #define PB push_back //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RS(s) scanf("%s", s) #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i) #define CPY(a, b) memcpy(a, b, sizeof(a)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) #define EQ(a, b) (fabs((a) - (b)) <= 1e-10) #define ALL(c) (c).begin(), (c).end() #define SZ(V) (int)V.size() #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p) #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q) #define WI(n) printf("%d\n", n) #define WS(s) printf("%s\n", s) #define sqr(x) x * x typedef long long LL; typedef vector <int> VI; typedef unsigned long long ULL; const double eps = 1e-10; const LL MOD = 1e9 + 7; using namespace std; const int maxn = 1010; const int INF = 0x3f3f3f3f; inline int ABS(int x) {if (x < 0) return -x; return x; } int pos[55][maxn], cost[55][maxn]; int dp[55][maxn]; int main() { int T, n, m, x; RI(T); while (T--) { RIII(n, m, x); REP(i, n) REP(j, m) RI(pos[i][j]); REP(i, n) REP(j, m) RI(cost[i][j]); REP(i, m) dp[0][i] = ABS(x - pos[0][i]) + cost[0][i]; FE(i, 1, n - 1) REP(j, m) { int t = INF; REP(k, m) { // dp[i][j] = min(dp[i][j], dp[i - 1][k] + ABS(pos[i][j] - pos[i - 1][k])); int x = dp[i - 1][k] + ABS(pos[i][j] - pos[i - 1][k]); if (x < t) t = x; } dp[i][j] = t + cost[i][j]; } int ans = INF; REP(i, m) ans = min(ans, dp[n - 1][i]); WI(ans); } return 0; }
hdu4362 dp + 单调队列优化,布布扣,bubuko.com
原文地址:http://blog.csdn.net/colin_27/article/details/37724663