BZOJ 1003 物流运输 (dijkstra & dp) - xgtao -

物流运输

 

1003: [ZJOI2006]物流运输

 

给出m(<=20)个点,e条边,从1走到m一共n(<=100)天,但是某一些点会在a~b这段时间里面关闭,所以就要更换落线,每一次更换路线都要消耗权值k,问在n天里从1到m的最小花费。

 

首先数据范围是很小的,就可以维护在某一段时间里的最短路。

那么再定义状态dp[i]表示前前i天所花费的权值。转移方程不难写出f[i] = min(dijkstra(1,i),f[j]+dijkstra(j+1,n)+k).

 

 

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 110;
const int E = 20010;
const int inf = 1<<30;

int n,m,k,e,d;
int f[N],dis[N];
bool done[N],flag[N][N];
struct edge{
	int v,w;
	edge *nxt;
}*head[N],*cur,meo[E];

struct node{
	int dis,u;
	bool operator < (const node &rhs)const{
		return dis>rhs.dis;
	}
};

void addedge(int u,int v,int w){
	cur->v = v;
	cur->w = w;
	cur->nxt = head[u];
	head[u] = cur++;
	
	cur->v = u;
	cur->w = w;
	cur->nxt = head[v];
	head[v] = cur++;
}

int dijkstra(int s,int t){
	priority_queue <node> q;
	memset(done,false,sizeof(done));
	for(int i = 1;i <= m;++i)
	for(int j = s;j <= t;++j){
		if(flag[i][j]){
			done[i] = true;
			break;
		}
	}
	for(int i = 1;i <= m;++i)dis[i] = inf;
	dis[1] = 0;
	q.push((node){dis[1],1});
	while(!q.empty()){
		node p = q.top();q.pop();
		int u = p.u;
		if(done[u])continue;
		done[u] = true;
		for(edge *it = head[u];it;it = it->nxt){
			int v = it->v;
			if(done[v])continue;
			if(dis[v] > dis[u]+it->w){
				dis[v] = dis[u]+it->w;
				q.push((node){dis[v],v});
			}
		}
	}
	return (dis[m] == inf) ? dis[m] : dis[m]*(t-s+1);
}

int main(){
	cur = meo;
	ios::sync_with_stdio(false);
	cin>>n>>m>>k>>e;
	for(int i = 1;i <= e;++i){
		int u,v,w;
		cin>>u>>v>>w;
		addedge(u,v,w);
	}
	cin>>d;
	for(int i = 1;i <= d;++i){
		int p,a,b;
		cin>>p>>a>>b;
		for(int j = a;j <= b;++j)flag[p][j] = true;
	}
	for(int i = 1;i <= n;++i){
		f[i] = dijkstra(1,i);
		for(int j = 1;j < i;++j){
			f[i] = min(f[i],f[j]+dijkstra(j+1,i)+k);
		}
	}
	cout<<f[n]<<endl;
	return 0;
}

  

posted @ 2016-07-26 11:13  xgtao984  阅读(174)  评论(0编辑  收藏  举报