1. 程式人生 > >2016 計蒜之道 復賽 百度地圖的實時路況

2016 計蒜之道 復賽 百度地圖的實時路況

int 思想 matrix 我們 set 最短路 限定 地圖 def

巧妙的解法。

首先直接限定每一個點不走跑$floyd$是$n^4$的,會超時,我們在$floyd$的時候加入分治思想,用$solve(l, r)$表示不考慮$[l, r]$區間的點所能得到的最短路,然後每一層處理一下就好了,直到最後一層就更新到答案中去。

時間復雜度$O(n^3logn)$。

我的代碼在$Windows$下一運行就爆棧。

Code:

技術分享圖片
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int N = 305;
const ll inf = 0x3f3f3f3f3f3f3f3f; int n; ll ans = 0LL; struct Matrix { ll s[N][N]; inline void init() { memset(s, 0x3f, sizeof(s)); } inline ll* operator [] (const int now) { return s[now]; } }; template <typename T> inline
void read(T &X) { X = 0; char ch = 0; T op = 1; for(; ch > 9 || ch < 0; ch = getchar()) if(ch == -) op = -1; for(; ch >= 0 && ch <= 9; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } template <typename T> inline
void chkMin(T &x, T y) { if(y < x) x = y; } void solve(int l, int r, Matrix now) { if(l == r) { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i != l && j != l) ans += (now[i][j] == inf) ? -1 : now[i][j]; return; } Matrix tmp = now; int mid = ((l + r) >> 1); for(int k = mid + 1; k <= r; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) chkMin(tmp[i][j], tmp[i][k] + tmp[k][j]); solve(l, mid, tmp); tmp = now; for(int k = l; k <= mid; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) chkMin(tmp[i][j], tmp[i][k] + tmp[k][j]); solve(mid + 1, r, tmp); } int main() { read(n); Matrix a; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { read(a[i][j]); if(a[i][j] == -1) a[i][j] = inf; } /* printf("\n"); for(int i = 1; i <= n; i++, printf("\n")) for(int j = 1; j <= n; j++) printf("%lld ", a[i][j]); */ solve(1, n, a); printf("%lld\n", ans); return 0; }
View Code

2016 計蒜之道 復賽 百度地圖的實時路況