BZOJ 1003 物流运输(dp+dijkstra)
传送门
题解:
由因为天的数量的只有100,并且只有20个港口,数据量很小。因此,可以直接用最短路预处理第i天到第j天用同一种路径所需要的花费。然后,预处理之后,用一个简单的dp就可以了。其中表示到第i天的最小花费,第i天到第j天用同一种路径所需要的花费,k是换方案的费用。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+50;
const int inf = 2e9;
long long cost[25];
long long c[105][105];
bool vis[25];
long long dp[105];
bool vis0[25][105];
bool flag[105];
struct node
{
int id,dis;
node(int x):id(x),dis(cost[x]){};
bool operator<(const node& b)const
{
return dis<b.dis;
}
};
struct edge
{
int next,to,w;
}e[maxn];
int head[maxn*2],tot;
void add(int u,int v,int w)
{
e[tot].to=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot++;
}
void dijkstra(int n)
{
//memset(vis,0,sizeof(vis));
memset(cost,0x7f,sizeof(cost));
cost[1]=0;
priority_queue<node>Q;
Q.push(node(1));
while(!Q.empty())
{
node temp=Q.top();
vis[temp.id]=1;
Q.pop();
for(int i=head[temp.id];i!=-1;i=e[i].next)
{
//if(vis[e[i].to]) continue;
if(cost[temp.id]+e[i].w<cost[e[i].to]&&!flag[e[i].to])
{
cost[e[i].to]=cost[temp.id]+e[i].w;
Q.push(node(e[i].to));
}
}
}
}
int main()
{
memset(head,-1,sizeof(head));
int i,j,n,m,k,N,M;
cin>>n>>m>>k>>N;
int w,u,v;
for(i=0;i<N;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
cin>>M;
for(i=0;i<M;i++)
{
scanf("%d%d%d",&w,&u,&v);
for(j=u;j<=v;j++) vis0[w][j]=1;
}
for(i=1;i<=n;i++)
{
for(j=i;j<=n;j++)
{
memset(flag,0,sizeof(flag));
for(int k=1;k<=m;k++)
{
for(int s=i;s<=j;s++)
flag[k]|=vis0[k][s];
}
dijkstra(m);
//cout<<cost[m]<<endl;
c[i][j]=cost[m];
}
}
for(i=1;i<=n;i++)
for(j=i;j<=n;j++)
if(c[i][j]<inf) c[i][j]*=1ll*(j-i+1);
memset(dp,0x7f,sizeof(dp));
for(i=1;i<=n;i++) dp[i]=c[1][i];
for(i=2;i<=n;i++)
{
for(j=1;j<i;j++)
{
dp[i]=min(dp[i],dp[j]+c[j+1][i]+k);
}
}
cout<<dp[n]<<endl;
}
Q.E.D.