【P1772 [ZJOI2006]物流运输】题解

2021年11月24日 阅读数:2
这篇文章主要向大家介绍【P1772 [ZJOI2006]物流运输】题解,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

题目连接

一道很好的最短路+dp。node

先考虑最后结果,设 \(dp_i\) 表示前 \(i\) 天的最小费用。设 \(f(i, j)\) 为从第 \(i\) 天到第 \(j\) 天都走同一条道路的最小费用。c++

\(f(i, j)\) 很好求,提早预处理这段时间内哪些点不能走而后再能够走的点内跑一遍最短路便可。spa

转移:code

\(dp_i=\min_{j=1}^i(dp_j+f(j+1, i)\times(i-(j+1)+1)+k)\)get

初始化 \(dp_i=f(1, i)\times i\)it

因为数据范围很小,彻底没问题。class

注意点:test

  1. 记得开 long long变量

  2. 变量有点多,别搞混queue

Code:

// Problem: P1772 [ZJOI2006]物流运输
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1772
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std; 
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M 
//#define mo
#define N 300
struct node
{
	int k, x, y, z, n; 
}d[N*2], a[N]; 
int n, m, i, j, k; 
int h[N], dp[N], f[N][N]; 
int p[N], c[N], ans[N]; 
int u, v, w, K, dy, g; 
queue<int> q; 

void cun(int x, int y, int z)
{
	d[++k].x=x; d[k].y=y; d[k].z=z; 
	d[k].n=h[x]; h[x]=k; 
}

int spfa(int s, int t)
{
	while(!q.empty()) q.pop(); 
	memset(ans , 0x3f, sizeof(ans)); 
	memset(p, 0, sizeof(p)); 
	memset(c, 0, sizeof(c)); 
	// for(int i=1; i<=n; ++i) ans[i]=1000000000;
	for(int i=1; i<=m; ++i)
	{
		if(a[i].y<s) continue; 
		if(a[i].x>t) continue; 
		p[a[i].k]=1; 
	}
	// for(int i=1; i<=n; ++i) printf("%lld ", p[i]); 
	q.push(1); c[1]=1; 
	ans[1]=0; 
	while(!q.empty())
	{
		u=q.front(); q.pop(); 
		c[u]=0; 
		// printf("%lld ", u); 
		for(g=h[u]; g; g=d[g].n)
		{
			v=d[g].y; w=d[g].z; 
			if(p[v]) continue; 
			if(ans[u]+w<ans[v])
			{
				ans[v]=ans[u]+w; 
				if(!c[v]) q.push(v), c[v]=1; 
			}
		}
	}
	// printf("%lld\n", ans[n]); 
	return ans[n];  
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin);
//	freopen("tiaoshi.out", "w", stdout);
	dy=read(); n=read(); K=read(); m=read(); 
	for(i=1; i<=m; ++i)
	{
		u=read(); v=read(); w=read(); 
		cun(u, v, w); cun(v, u, w); 
	}
	m=read(); 
	for(i=1; i<=m; ++i)
	{
		a[i].k=read(); 
		a[i].x=read(); a[i].y=read(); 
	}
	for(i=1; i<=dy; ++i)
		for(j=i; j<=dy; ++j)
			f[i][j]=spfa(i, j); 
	memset(dp, 0x7f, sizeof(dp)); 
	for(i=1; i<=dy; ++i)
	{
		dp[i]= (f[1][i]==0x3f3f3f3f3f3f3f3f) ? 0x3f3f3f3f3f3f3f3f : f[1][i]*i;  
		// dp[i]=f[1][i]*i; 
		
		for(j=0; j<i; ++j)
			if(f[j+1][i]!=0x3f3f3f3f3f3f3f3f)
				dp[i]=min(dp[i], dp[j]+f[j+1][i]*(i-(j+1)+1)+K); 
		// printf("dp[%lld]=%lld\n", i, dp[i]); 
	}
	printf("%lld", dp[dy]); 
	return 0; 
}