zoukankan      html  css  js  c++  java
  • [ZJOI2006]物流运输

    Description

    BZOJ1003

    Solution

    这个题一开始没有什么思路,看了黄学长的blog,才发现这个题是个很暴力的DP,设(f[i])为前(i)天的花费,(dist[i][j])([i,j])这几天的最短路径长度,则易得(f[i] = min{dist[1][i], f[j-1]+k+dist[j][i]})。然后,dist数组竟然是暴力跑(n^2)遍最短路,复杂度(O(n^2cdot (m+n)logn)),虽然看起来过不了,但是由于会有很多点被ban掉,而且也跑不满,所以还是可以过掉的(再说时限10s怎么着也不会TLE吧)。

    Code

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    
    const int N = 25;
    const int M = 110;
    const int E = N*N;
    const int INF = 1e9;
    typedef long long LL;
    
    LL dist[M][M], f[M];
    int hd[N], to[E], nxt[E], w[E], cnt;
    int ban[M][N];
    int vis[N], dis[N];
    int n, m, e, k;
    struct node {
    	int pos, w;
    	node (int a = 0, int b = 0) : pos(a), w(b) {};
    	bool operator < (const node &a) const {
    		return w > a.w;
    	}
    };
    std::priority_queue<node> q;
    
    void adde(int x, int y, int z) {
    	cnt++;
    	to[cnt] = y;
    	nxt[cnt] = hd[x];
    	w[cnt] = z;
    	hd[x] = cnt;
    } 
    
    int dij(int s, int t) {
    	memset(vis, 0, sizeof vis);
    	for (int i = 2; i <= m; ++i) dis[i] = INF;
    	for (int i = s; i <= t; ++i) {
    		for (int j = 2; j < m; ++j) {
    			if (ban[i][j]) vis[j] = 1;
    		}
    	}
    	q.push(node(1, 0));
    	dis[1] = 0;
    	node tmp;
    	while (!q.empty()) {
    		tmp = q.top(); q.pop();
    		if (vis[tmp.pos]) continue;
    		vis[tmp.pos] = 1;
    		for (int i = hd[tmp.pos]; i; i = nxt[i]) if (!vis[to[i]]) {
    			if (dis[to[i]] > tmp.w + w[i]) {
    				dis[to[i]] = tmp.w + w[i];
    				q.push(node(to[i], dis[to[i]]));
    			}
    		}
    	}
    	return dis[m];
    }
    
    int main() {
    	scanf("%d%d%d%d", &n, &m, &k, &e);
    	for (int i = 1, x, y, z; i <= e; ++i) {
    		scanf("%d%d%d", &x, &y, &z);
    		adde(x, y, z);
    		adde(y, x, z);
    	}
    	int d;
    	scanf("%d", &d);
    	for (int i = 1, x, y, z; i <= d; ++i) {
    		scanf("%d%d%d", &z, &x, &y);
    		for (int j = x; j <= y; ++j) {
    			ban[j][z] = 1; // mark
    		}
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (int j = i; j <= n; ++j) {
    			dist[i][j] = dij(i, j);
    		}
    	}
    	f[0] = 0;
    	for (int i = 1; i <= n; ++i) {
    		f[i] = (LL)dist[1][i] * i;
    		//printf("%d
    ", f[i]);
    		for (int j = 1; j <= i; ++j) {
    			f[i] = std::min(f[i], f[j-1]+k+(LL)dist[j][i]*(i-j+1));
    		}
    	}
    	printf("%lld
    ", f[n]);
    	return 0;
    }
    

    Note

    mark的那个地方我竟然写成了ban[j][i],还是要更仔细。其实这个数据范围是要开long long的,不过好像没有刻意卡,但还是要注意。

  • 相关阅读:
    Android实战——第三方服务之Bmob后端云的集成、用户登陆、用户注册、获取用户、用户注销(一)
    Android实战——第三方服务之Bmob后端云的答题系统小项目(四)
    10.Python运行Scrapy时出现错误: ModuleNotFoundError: No module named 'win32api'
    基础小知识(1)
    9.Python安装scrapy教程
    1.使用Fiddler进行接口测试
    8.Python编写登录接口
    18.Selenium+Python案例 -- 豆瓣
    17.Selenium+Python日期控件小案例
    16.Selenium+Python关于句柄的小Demo
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1003.html
Copyright © 2011-2022 走看看