luogu P1772 [ZJOI2006]物流运输 spfa最短路+dp

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=4005;
const int inf=0x3f3f3f3f;
//求这n天每天从1到m的距离和与更改道路的价值之和的最小值.
int dp[N],now[N],limit[N][N],dist[N];
bool st[N];
int h[N],e[N],ne[N],idx,w[N];
int n,m,K,E;
int a,b,c,d,p;
void add(int a,int b,int c)
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
int spfa()
{
	memset(dist,inf,sizeof dist);
	queue<int>q;
	q.push(1);
	dist[1]=0;
	st[1]=1;
	while(q.size())
	{
		int u=q.front();
		q.pop();
		st[u]=0;
		for(int i=h[u]; i!=-1; i=ne[i])
		{
			int j=e[i];
			if(dist[j]>dist[u]+w[i]&&now[j]==0)
			{
				dist[j]=dist[u]+w[i];
				if(st[j]==0)
				{
					st[j]=1;
					q.push(j);
				}
			}
		}
	}
	return dist[m];
}
int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m>>K>>E;
	for(int i=1; i<=E; i++)
	{
		cin>>a>>b>>c;
		add(a,b,c);
		add(b,a,c);
	}
	cin>>d;
	for(int i=1; i<=d; i++)
	{
		cin>>p>>a>>b;
		//码头p 从a到b天内无法使用 
		for(int j=a; j<=b; j++)
			limit[j][p]=1;
	}
	memset(dp,inf,sizeof dp);
	dp[0]=-K;//第一次选择路径是不算做跟改路径的
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=m; j++)
			now[j]=0;
		for(int j=i; j>=1; j--)
		{
			for(int k=1; k<=m; k++)
				if(limit[j][k])
					now[k]=1;
			int get=spfa();
			if(get>=inf)
				break;
			//如果取后者,就说明改路线了 
			dp[i]=min(dp[i],dp[j-1]+(i-j+1)*get+K);
		}
	}
	cout<<dp[n]<<endl;
	return 0;
}
posted @ 2020-05-18 17:26  晴屿  阅读(102)  评论(0编辑  收藏  举报