传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1003
核心是dp,方程如下
dp[i]=min(dp[i],dp[j]+dis[j+1][i]∗(j−i+1)+K)(j<i)
d
p
[
i
]
=
m
i
n
(
d
p
[
i
]
,
d
p
[
j
]
+
d
i
s
[
j
+
1
]
[
i
]
∗
(
j
−
i
+
1
)
+
K
)
(
j
<
i
)
其中
dp[i]:第一天到第i天的最小代价
dis[i]:i天到j天从1到m的最短路
还是很好理解的,预处理dp[i]=dis[1][i](dis[i]用spfa可以预处理出来)
前面的就是不换航线成本,后面那串就是j到i这几天换航线的成本
code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxm=1100;
const int maxn=110;
const int INF=99999999;
struct node
{
int x,y,c,next;
}a[maxm*2]; int len,last[maxm];
void ins(int x,int y,int c)
{
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
}
bool cango[maxm][maxn];//第i个点,第j天不能走
bool nowgo[maxm];//在当前时间内,i能不能走
int n,m;//n天数,m码头总数
int d[maxm]; bool v[maxm];
int list[maxm],head,tail;
queue<int> q;
inline int spfa(int fr,int to)
{
for(int i=1;i<=m;i++)
for(int j=fr;j<=to;j++)
nowgo[i]|=cango[i][j];
for(int i=1;i<=m;i++) d[i]=INF; d[1]=0;
memset(v,false,sizeof(v)); v[1]=true;
head=1,tail=2; list[head]=1;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x]+a[k].c && !nowgo[y])
{
d[y]=d[x]+a[k].c;
if(!v[y])
{
v[y]=true;
list[tail++]=y;
}
}
}
head++;
v[x]=false;
}
return d[m];
}
int dp[maxn];//dp[i]:第一天到第i天的最小代价
int dis[maxm][maxm];//i天到j天从1到m的最短路
int K;
//dp[i]=min{dp[i],dp[j]+dis[i][j]*(i-j)+K} (j<i)
int main()
{
freopen("trans.in","r",stdin);
freopen("trans.out","w",stdout);
int e;scanf("%d%d%d%d",&n,&m,&K,&e);
len=0,memset(last,0,sizeof(last));
for(int i=1;i<=e;i++)
{
int x,y,c;scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);
ins(y,x,c);
}
int d;scanf("%d",&d);
for(int i=1;i<=d;i++)
{
int P,a,b;scanf("%d%d%d",&P,&a,&b);
for(int j=a;j<=b;j++) cango[P][j]=true;
}
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
memset(nowgo,0,sizeof(nowgo));
dis[i][j]=spfa(i,j);
}
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j++)
if (dis[i][j]<INF) dis[i][j]*=(j-i+1);
for(int i=1;i<=n;i++) dp[i]=dis[1][i];
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
{
if(dis[j+1][i]<INF)
{
dp[i]=min(dp[i],dp[j]+dis[j+1][i]+K);
}
}
printf("%d\n",dp[n]);
return 0;
}