1003: [ZJOI2006]物流运输
题意:m个码头,从码头1到码头m,连续n天都要运送货物。每一天的花费是总路线长度大小,但如果和前一天的路线不一样,要另处加上k元花费。而且有些码头有些天不能用,问这n天的最小费用。
tags:菜鸡一开始真没想到是dp
求n天时最小花费,就要想到以天数为阶段进行规划。dp[i][j]表示第i天到第j天走同一条路线的花费,则f[i]=min( f[i], f[j]+dp[j+1][i]+k )。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (int i=a;i<=b;i++) #define F(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 200; const ll inf=1e18; int n, m, k, e1, d1, q[10000], head[N], tot; ll c[N][N], dis[N], f[N]; bool vis[N], use[N], flag[N][N]; struct Edge{int to, next; ll w;}e[N*N]; void Addedge(int u, int v, ll w) { e[++tot].to=v, e[tot].w=w, e[tot].next=head[u], head[u]=tot; }; ll spfa(int x, int y) { mes(use, 0); mes(vis, 0); FF(i,1,m) dis[i]=inf; dis[1]=0; FF(i,x,y) FF(j,1,m) if(flag[j][i]) use[j]=1; int t=0, h=0; q[++t]=1, dis[1]=0; while(h!=t) { int u=q[++h]; vis[u]=1; for(int i=head[u]; i; i=e[i].next) { int v=e[i].to; ll w=e[i].w; if(use[v]==0 && dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if(vis[v]==0) q[++t]=v, vis[v]=1; } } vis[u]=0; } return dis[m]*(dis[m]>=inf ? 1 : (y-x+1)); } void Init() { scanf("%d %d %d %d", &n, &m, &k, &e1); int u, v, p, a, b; ll w; FF(i,1,e1) { scanf("%d %d %lld", &u, &v, &w); Addedge(u, v, w); Addedge(v, u, w); } scanf("%d", &d1); FF(i,1,d1) { scanf("%d %d %d", &p, &a, &b); FF(j,a,b) flag[p][j]=1; } FF(i,1,n) FF(j,1,i) c[j][i]=spfa(j, i); } void DP() { FF(i,1,n) { f[i]=c[1][i]; FF(j,1,i-1) f[i]=min(f[i], f[j]+c[j+1][i]+k); } printf("%lld\n", f[n]); } int main() { //freopen("in.txt", "r", stdin); Init(); DP(); return 0; }
时间: 2024-10-12 23:51:16