列表

详情


NC20522. [ZJOI2016]旅行者

描述

小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)最少需要 花多少时间。

输入描述

第一行包含 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,表示两个路口的位置。

输出描述

输出共q行,每行包含一个整数表示从一个路口到另一个路口最少需要花的时间。

示例1

输入:

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

输出:

6
7

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 767ms, 内存消耗: 6264K, 提交时间: 2020-04-29 17:09:05

#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int read()
{
    int x = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
    while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
const int MAX = 200033;
const int inf = 100000000;
#define id(i, j) ((i - 1) * m + (j))
int n, m, cnte, Q, cntid;
int invx[20033], invy[20033];
int fir[20033];
struct Query
{
    int x, y, xx, yy, id;
} q[100033], tmp[100033];
struct edge
{
    int to, nxt, w;
    edge() {}
    edge(int a, int b, int c)
    {
        to = a, nxt = b, w = c;
    }
} e[200033];
void addedge(int u, int v, int w)
{
    e[++cnte] = edge(v, fir[u], w), fir[u] = cnte;
    e[++cnte] = edge(u, fir[v], w), fir[v] = cnte;
}
int ans[100033], dis[20033];
int que[2000033];
bool inq[20033];
void dijkstra(int s, int xl, int xr, int yl, int yr, int h)
{
    int d = dis[s];
    for (int i = xl; i <= xr; i++)
        for (int j = yl; j <= yr; j++)
            dis[id(i, j)] = h ? dis[id(i, j)] + d : inf;
    dis[s] = 0;
    inq[s] = 1; 
    int l = 10000, r = 10000;
    que[r++] = s;
    while (l != r)
    {
        int u = que[l++];
        inq[u] = 0;
        for (int i = fir[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            int vy = invy[v], vx = invx[v];
            if (vx >= xl && vx <= xr && vy >= yl && vy <= yr)
                if (dis[v] > dis[u] + e[i].w)
                {
                    dis[v] = dis[u] + e[i].w;
                    if (!inq[v])
                    {
                        if (dis[v] <= dis[que[l]])
                            que[--l] = v;
                        else que[r++] = v;
                        inq[v] = 1;
                    }
                }
        }
    }
}
void solve(int xl, int xr, int yl, int yr, int ql, int qr)
{
    if (ql > qr) return;
    if (xr - xl > yr - yl)
    {
        int mid = (xl + xr) >> 1;
        for (int i = yl; i <= yr; i++)
        {
            dijkstra(id(mid, i), xl, xr, yl, yr, i - yl);
            for (int j = ql; j <= qr; j++)
                ans[q[j].id] = min(ans[q[j].id], dis[id(q[j].x, q[j].y)] + dis[id(q[j].xx, q[j].yy)]);
        }
        int l = ql - 1, r = qr + 1;
        for (int i = ql; i <= qr; i++)
        {
            if (q[i].x < mid && q[i].xx < mid)
                tmp[++l] = q[i];
            else if (q[i].x > mid && q[i].xx > mid)
                tmp[--r] = q[i];
        }
        for (int i = ql; i <= l; i++)
            q[i] = tmp[i];
        for (int i = r; i <= qr; i++)
            q[i] = tmp[i];
        solve(xl, mid - 1, yl, yr, ql, l);
        solve(mid + 1, xr, yl, yr, r, qr);
    }
    else
    {
        int mid = (yl + yr) >> 1;
        for (int i = xl; i <= xr; i++)
        {
            dijkstra(id(i, mid), xl, xr, yl, yr, i - xl);
            for (int j = ql; j <= qr; j++)
                ans[q[j].id] = min(ans[q[j].id], dis[id(q[j].x, q[j].y)] + dis[id(q[j].xx, q[j].yy)]);
        }
        int l = ql - 1, r = qr + 1;
        for (int i = ql; i <= qr; i++)
        {
            if (q[i].y < mid && q[i].yy < mid)
                tmp[++l] = q[i];
            else if (q[i].y > mid && q[i].yy > mid)
                tmp[--r] = q[i];
        }
        for (int i = ql; i <= l; i++)
            q[i] = tmp[i];
        for (int i = r; i <= qr; i++)
            q[i] = tmp[i];
        solve(xl, xr, yl, mid - 1, ql, l);
        solve(xl, xr, mid + 1, yr, r, qr);
    }
}
int main()
{
    memset(ans, 63, sizeof ans);
    n = read(), m = read();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            cntid++;
            invx[cntid] = i, invy[cntid] = j;
        }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j < m; j++)
            addedge(id(i, j), id(i, j + 1), read());
    for (int i = 1; i < n; i++)
        for (int j = 1; j <= m; j++)
            addedge(id(i, j), id(i + 1, j), read());
    Q = read();
    for (int i = 1; i <= Q; i++)
    {
        q[i].x = read(), q[i].y = read();
        q[i].xx = read(), q[i].yy = read();
        q[i].id = i;
    }
    solve(1, n, 1, m, 1, Q);
    for (int i = 1; i <= Q; i++)
        printf("%d\n", ans[i]);
    return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 1768ms, 内存消耗: 5580K, 提交时间: 2022-09-29 03:38:17

#include <iostream>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

using PII = pair<int, int>;

const int N = 250010, M = 2500010, INF = 0x3f3f3f3f;
const int dir[][2] = {-1, 0, 0, 1, 1, 0, 0, -1};

int n, m, Q;
int dis[N];
bool vis[N];
struct Node {
	int x0, y0, x1, y1, id;
} q[N], tmp[N];
vector<vector<int>> r, c, id;
int ans[N];
int v[4][N];

void dijkstra(int xl, int xr, int yl, int yr, int S) {
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    for (int i = xl; i <= xr; i++)
    	for (int j = yl; j <= yr; j++)
    		dis[id[i][j]] = INF, vis[id[i][j]] = false;
    dis[S] = 0, heap.push({0, S});
    while (heap.size()) {
        auto [d, t] = heap.top();
        heap.pop();
        if (vis[t]) continue;
        vis[t] = true;
        int x = (t - 1) / m + 1, y = (t - 1) % m + 1;
        for (int u = 0; u < 4; u++) {
        	int tx = x + dir[u][0], ty = y + dir[u][1];
        	if (tx < xl || tx > xr || ty < yl || ty > yr) continue;
        	int nt = id[tx][ty];
        	if (d + v[u][t] < dis[nt]) {
        		dis[nt] = d + v[u][t];
        		heap.push({dis[nt], nt}); 
        	} 
        }
    }
}

void solve(int xl, int xr, int yl, int yr, int ql, int qr) {
	if (xl > xr || yl > yr || ql > qr) return;
	int deltax = xr - xl, deltay = yr - yl;
	if (deltax > deltay) {
		int mid = xl + xr >> 1;
		for (int i = yl; i <= yr; i++) {
			dijkstra(xl, xr, yl, yr, id[mid][i]);
			for (int j = ql; j <= qr; j++) {
				auto& [x0, y0, x1, y1, o] = q[j];
				ans[o] = min(ans[o], dis[id[x0][y0]] + dis[id[x1][y1]]);
			}
		}
		int l = ql - 1, r = qr + 1;
		for (int i = ql; i <= qr; i++) {
			if (q[i].x0 < mid && q[i].x1 < mid) tmp[++l] = q[i];
			else if (q[i].x0 > mid && q[i].x1 > mid) tmp[--r] = q[i];
		}
		for (int i = ql; i <= l; i++) q[i] = tmp[i];
		for (int i = r; i <= qr; i++) q[i] = tmp[i];
		solve(xl, mid, yl, yr, ql, l);
		solve(mid + 1, xr, yl, yr, r, qr);
	}
	else {
		int mid = yl + yr >> 1;
		for (int i = xl; i <= xr; i++) {
			dijkstra(xl, xr, yl, yr, id[i][mid]);
			for (int j = ql; j <= qr; j++) {
				auto& [x0, y0, x1, y1, o] = q[j];
				ans[o] = min(ans[o], dis[id[x0][y0]] + dis[id[x1][y1]]);
			}
		}
		int l = ql - 1, r = qr + 1;
		for (int i = ql; i <= qr; i++) {
			if (q[i].y0 < mid && q[i].y1 < mid) tmp[++l] = q[i];
			else if (q[i].y0 > mid && q[i].y1 > mid) tmp[--r] = q[i];
		}
		for (int i = ql; i <= l; i++) q[i] = tmp[i];
		for (int i = r; i <= qr; i++) q[i] = tmp[i];
		solve(xl, xr, yl, mid, ql, l);
		solve(xl, xr, mid + 1, yr, r, qr);
	}
}

int main() {
    cin >> n >> m;
    c = r = id = vector<vector<int>>(n + 5, vector<int>(m + 5));
    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= m; j++)
    		id[i][j] = (i - 1) * m + j;
    for (int i = 1; i <= n; i++) {
    	for (int j = 1; j < m; j++) {
    		cin >> r[i][j];
    		v[1][id[i][j]] = v[3][id[i][j + 1]] = r[i][j];
    	}
    }
	for (int i = 1; i < n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> c[i][j];
			int t = id[i][j];
			v[2][id[i][j]] = v[0][id[i + 1][j]] = c[i][j];
		}
	}
	cin >> Q;
	for (int i = 1; i <= Q; i++) {
		auto& [x0, y0, x1, y1, id] = q[i];
		cin >> x0 >> y0 >> x1 >> y1;
		id = i;
	}
	memset(ans, 0x3f, sizeof ans);
	solve(1, n, 1, m, 1, Q);
	for (int i = 1; i <= Q; i++)
		cout << ans[i] << '\n';
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 1663ms, 内存消耗: 5100K, 提交时间: 2022-10-24 16:52:13

#include<bits/stdc++.h>
using namespace std;

#define pos(x,y) (x-1)*m+y
#define add(x,y,z) G[x].push_back({y,z}),G[y].push_back({x,z})
typedef pair<int,int> pa;
const int MAXN=2e4+5;
const int MAXQ=1e5+5;
const int INF=0x3f3f3f3f;
struct point
{
    int sx,sy,tx,ty;
}input[MAXQ];
vector<pa>G[MAXN];
int dis[MAXN];
bool vis[MAXN];
int query[MAXQ],tmp1[MAXQ],tmp2[MAXQ],ans[MAXQ];
int n,m,q;
void dijkstra(int lx,int rx,int ly,int ry,int s)
{
    priority_queue< pa,vector<pa>,greater<pa> >q;
    for(int i=lx;i<=rx;++i) for(int j=ly;j<=ry;++j) dis[pos(i,j)]=INF,vis[pos(i,j)]=0;
    dis[s]=0,q.push({dis[s],s});
    while(!q.empty())
    {
        int x=q.top().second;q.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(auto [y,z]:G[x])
        {
            int xx,yy;
            yy=(y%m==0)?m:y%m;
            xx=(y-yy)/m+1;
            if(!(lx<=xx && xx<=rx && ly<=yy && yy<=ry)) continue;
            if(dis[y]>dis[x]+z) dis[y]=dis[x]+z,q.push({dis[y],y});
        }
    }
}
void dfs(int lx,int rx,int ly,int ry,int lq,int rq)
{
    if(lx>rx || ly>ry || lq>rq) return;
    if(rx-lx>ry-ly)
    {
        int mid=(lx+rx)>>1;
        for(int i=ly;i<=ry;++i)
        {
            dijkstra(lx,rx,ly,ry,pos(mid,i));
            for(int j=lq;j<=rq;++j) ans[query[j]]=min(ans[query[j]],dis[pos(input[query[j]].sx,input[query[j]].sy)]+dis[pos(input[query[j]].tx,input[query[j]].ty)]);
        }
        int cnt1=0,cnt2=0;
        for(int i=lq;i<=rq;++i)
        {
            if((input[query[i]].sx<=mid && input[query[i]].tx>=mid) || (input[query[i]].tx<=mid && input[query[i]].sx>=mid)) continue;
            if(input[query[i]].sx<mid) tmp1[++cnt1]=query[i];
            else tmp2[++cnt2]=query[i];
        }
        for(int i=lq,j=1;j<=cnt1;++i,++j) query[i]=tmp1[j];
        for(int i=lq+cnt1,j=1;j<=cnt2;++i,++j) query[i]=tmp2[j];
        dfs(lx,mid-1,ly,ry,lq,lq+cnt1-1);
        dfs(mid+1,rx,ly,ry,lq+cnt1,lq+cnt1+cnt2-1);
    }
    else
    {
        int mid=(ly+ry)>>1;
        for(int i=lx;i<=rx;++i)
        {
            dijkstra(lx,rx,ly,ry,pos(i,mid));
            for(int j=lq;j<=rq;++j) ans[query[j]]=min(ans[query[j]],dis[pos(input[query[j]].sx,input[query[j]].sy)]+dis[pos(input[query[j]].tx,input[query[j]].ty)]);
        }
        int cnt1=0,cnt2=0;
        for(int i=lq;i<=rq;++i)
        {
            if((input[query[i]].sy<=mid && input[query[i]].ty>=mid) || (input[query[i]].ty<=mid && input[query[i]].sy>=mid)) continue;
            if(input[query[i]].sy<mid) tmp1[++cnt1]=query[i];
            else tmp2[++cnt2]=query[i];
        }
        for(int i=lq,j=1;j<=cnt1;++i,++j) query[i]=tmp1[j];
        for(int i=lq+cnt1,j=1;j<=cnt2;++i,++j) query[i]=tmp2[j];
        dfs(lx,rx,ly,mid-1,lq,lq+cnt1-1);
        dfs(lx,rx,mid+1,ry,lq+cnt1,lq+cnt1+cnt2-1);
    }
}
int main()
{
    cin>>n>>m;
    int x;
    for(int i=1;i<=n;++i) for(int j=1;j<m;++j) scanf("%d",&x),add(pos(i,j),pos(i,j+1),x);
    for(int i=1;i<n;++i) for(int j=1;j<=m;++j) scanf("%d",&x),add(pos(i,j),pos(i+1,j),x);
    cin>>q;
    for(int i=1;i<=q;++i) scanf("%d %d %d %d",&input[i].sx,&input[i].sy,&input[i].tx,&input[i].ty),query[i]=i;
    memset(ans,0x3f,sizeof(ans));
    dfs(1,n,1,m,1,q);
    for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
    return 0;
}

上一题