1. 程式人生 > >【BZOJ4456】 [Zjoi2016]旅行者 / 【UOJ #184】 【ZJOI2016】旅行者

【BZOJ4456】 [Zjoi2016]旅行者 / 【UOJ #184】 【ZJOI2016】旅行者

last opera ont 註意 ring += 兩個 oid 中間

Description

小Y來到了一個新的城市旅行。她發現了這個城市的布局是網格狀的,也就是有n條從東到西的道路和m條從南到北 的道路,這些道路兩兩相交形成n×m個路口 (i,j)(1≤i≤n,1≤j≤m)。她發現不同的道路路況不同,所以通過不 同的路口需要不同的時間。通過調查發現,從路口(i,j)到路口(i,j+1)需要時間 r(i,j),從路口(i,j)到路口(i+1 ,j)需要時間c(i,j)。註意這裏的道路是雙向的。小Y有q個詢問,她想知道從路口(x1,y1)到路口(x2,y2)最少需要 花多少時間。

Input

第一行包含 2 個正整數n,m,表示城市的大小。 接下來n行,每行包含m?1個整數,第i行第j個正整數表示從一個路口到另一個路口的時間r(i,j)。 接下來n?1行,每行包含m個整數,第i行第j個正整數表示從一個路口到另一個路口的時間c(i,j)。 接下來一行,包含1個正整數q,表示小Y的詢問個數。 接下來q行,每行包含4個正整數 x1,y1,x2,y2,表示兩個路口的位置。

Output

輸出共q行,每行包含一個整數表示從一個路口到另一個路口最少需要花的時間。

Sample Input

2 2
2
3
6 4
2
1 1 2 2
1 2 2 1

Sample Output

6
7

Solution

網格圖求任意兩點間的最短路。

可以用分治來解決。

之前校內訓練的時候CJK學長出了一道IOI2013的題,就是用線段樹來維護網格圖的最短路。這題也很類似,離線詢問以後,每次把長邊拿出來分治,考慮經過中間這一排點的和沒經過這一排點的。沒經過的遞歸下去做,經過的就跑一遍堆優化dj或者spfa就好了。

Code

  1
#include <cstdio> 2 #include <cstring> 3 4 #define R register 5 #define maxn 20010 6 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) 7 #define id(_a, _b) (((_a) - 1) * m + (_b) - 1) 8 #define id1(_x) ((_x) / m + 1) 9 #define id2(_x) ((_x) % m + 1) 10 int n, m;
11 struct Edge { 12 Edge *next; 13 int to, w; 14 } *last[maxn], e[maxn << 4], *ecnt = e; 15 inline void link(R int a, R int b, R int w) 16 { 17 *++ecnt = (Edge) {last[a], b, w}; last[a] = ecnt; 18 *++ecnt = (Edge) {last[b], a, w}; last[b] = ecnt; 19 } 20 struct Ques { 21 int x1, y1, x2, y2, id; 22 } qu[100010], tmp[100010]; 23 int ans[100010], dis[maxn], q[maxn * 50], r[maxn], c[maxn]; 24 bool inq[maxn]; 25 #define inf 0x7fffffff 26 struct Data { 27 int pos, dis; 28 inline bool operator < (const Data &that) const {return dis > that.dis;} 29 } ; 30 #include <queue> 31 std::priority_queue<Data> hp; 32 void spfa(R int s, R int nl, R int nr, R int ml, R int mr) 33 { 34 //for (R int i = nl; i <= nr; ++i) for (R int j = ml; j <= mr; ++j) dis[id(i, j)] = inf; 35 /* 36 R int head = maxn * 20, tail = maxn * 20 + 1; 37 q[maxn * 20 + 1] = s; dis[s] = 0; 38 */ 39 hp.push((Data) {s, dis[s] = 0}); 40 while (/*head < tail*/!hp.empty()) 41 { 42 // R int now = q[++head]; inq[now] = 0; 43 R Data tp = hp.top(); hp.pop(); 44 R int now = tp.pos; 45 for (R Edge *iter = last[now]; iter; iter = iter -> next) 46 if (dis[iter -> to] > dis[now] + iter -> w && nl <= id1(iter -> to) && id1(iter -> to) <= nr && ml <= id2(iter -> to) && id2(iter -> to) <= mr) 47 { 48 dis[iter -> to] = dis[now] + iter -> w; 49 // !inq[iter -> to] ? inq[dis[iter -> to] < dis[q[head + 1]] ? q[head--] = iter -> to : q[++tail] = iter -> to] = 1 : 0; 50 hp.push((Data) {iter -> to, dis[iter -> to]}); 51 } 52 } 53 } 54 void work(R int nl, R int nr, R int ml, R int mr, R int ql, R int qr) 55 { 56 if (nl > nr || ml > mr) return ; 57 if (ql > qr) return ; 58 if (nr - nl + 1 <= mr - ml + 1) 59 { 60 R int mid = ml + mr >> 1; 61 for (R int i = nl; i <= nr; ++i) for (R int j = ml; j <= mr; ++j) dis[id(i, j)] = inf; 62 for (R int i = nl; i <= nr; ++i) 63 { 64 if (i != nl) 65 { 66 for (R int ii = nl; ii <= nr; ++ii) for (R int jj = ml; jj <= mr; ++jj) 67 dis[id(ii, jj)] += c[id(i - 1, mid)]; 68 } 69 spfa(id(i, mid), nl, nr, ml, mr); 70 for (R int j = ql; j <= qr; ++j) 71 cmin(ans[qu[j].id], dis[id(qu[j].x1, qu[j].y1)] + dis[id(qu[j].x2, qu[j].y2)]); 72 } 73 R int qql = ql - 1, qqr = qr + 1; 74 for (R int i = ql; i <= qr; ++i) 75 if (qu[i].y1 < mid && qu[i].y2 < mid) 76 tmp[++qql] = qu[i]; 77 else if (qu[i].y1 > mid && qu[i].y2 > mid) 78 tmp[--qqr] = qu[i]; 79 80 for (R int i = ql; i <= qql; ++i) qu[i] = tmp[i]; 81 for (R int i = qqr; i <= qr; ++i) qu[i] = tmp[i]; 82 work(nl, nr, ml, mid - 1, ql, qql); 83 work(nl, nr, mid + 1, mr, qqr, qr); 84 } 85 else 86 { 87 R int mid = nl + nr >> 1; 88 for (R int i = nl; i <= nr; ++i) for (R int j = ml; j <= mr; ++j) dis[id(i, j)] = inf; 89 for (R int i = ml; i <= mr; ++i) 90 { 91 if (i != ml) 92 { 93 for (R int ii = nl; ii <= nr; ++ii) for (R int jj = ml; jj <= mr; ++jj) 94 dis[id(ii, jj)] += r[id(mid, i - 1)]; 95 } 96 spfa(id(mid, i), nl, nr, ml, mr); 97 for (R int j = ql; j <= qr; ++j) 98 cmin(ans[qu[j].id], dis[id(qu[j].x1, qu[j].y1)] + dis[id(qu[j].x2, qu[j].y2)]); 99 } 100 R int qql = ql - 1, qqr = qr + 1; 101 for (R int i = ql; i <= qr; ++i) 102 if (qu[i].x1 < mid && qu[i].x2 < mid) 103 tmp[++qql] = qu[i]; 104 else if (qu[i].x1 > mid && qu[i].x2 > mid) 105 tmp[--qqr] = qu[i]; 106 107 for (R int i = ql; i <= qql; ++i) qu[i] = tmp[i]; 108 for (R int i = qqr; i <= qr; ++i) qu[i] = tmp[i]; 109 work(nl, mid - 1, ml, mr, ql, qql); 110 work(mid + 1, nr, ml, mr, qqr, qr); 111 } 112 } 113 int main() 114 { 115 scanf("%d%d", &n, &m); 116 for (R int i = 1; i <= n; ++i) for (R int j = 1; j < m; ++j) 117 {R int w; scanf("%d", &w); link(id(i, j), id(i, j + 1), w); r[id(i, j)] = w;} 118 for (R int i = 1; i < n; ++i) for (R int j = 1; j <= m; ++j) 119 {R int w; scanf("%d", &w); link(id(i, j), id(i + 1, j), w); c[id(i, j)] = w;} 120 R int Q; scanf("%d", &Q); 121 for (R int i = 1; i <= Q; ++i) scanf("%d%d%d%d", &qu[i].x1, &qu[i].y1, &qu[i].x2, &qu[i].y2), qu[i].id = i; 122 memset(ans, 63, (Q + 1) << 2); 123 work(1, n, 1, m, 1, Q); 124 for (R int i = 1; i <= Q; ++i) printf("%d\n", ans[i]); 125 return 0; 126 }

【BZOJ4456】 [Zjoi2016]旅行者 / 【UOJ #184】 【ZJOI2016】旅行者