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

题目链接

一道很好的最短路+dp。

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

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

转移:

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

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

由于数据范围很小,完全没问题。

注意点:

  1. 记得开 long long

  2. 变量有点多,别搞混

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; 
}

上一篇:NOIP 模拟七 考试总结


下一篇:UVA610 Street Directions