DP+SPFA
题目大意:给定一个无向图,运输n天,其中有些天有些点不能走,更换路线代价为k,求代价总和
首先令cost[i][j]为第i天到第j天都走同一路线的最小花销 这个用SPFA预处理
然后就是动规的问题了 令f[i]为1~i天的最小花销
则f[i]=min{ f[j]+cost[j+1][i]+k } ( 0<=j<i )
注意m和n别写反
乘天数之前要特判是不是正无穷
我自己的代码:
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
long long first[201];
struct node
{
long long to;
long long next;
long long len;
};
node bian[40000];
long long cost[201][201];
long long n,m,k,d,e;
long long size;
bool used[205][205];
bool sta[201];
bool exist[205];
long long dis[205];
long long p[400001];
long long dp[201];
long long read()
{
long long k=0,f=1;
char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+(c-'0'); c=getchar();}
return k*f;
}
void inser(long long a,long long b,long long c)
{
size++;
bian[size].to=b;
bian[size].len=c;
bian[size].next=first[a];
first[a]=size;
}
long long spfa()
{
long long head=0;
memset(sta,0,sizeof(sta));
long long tail=1;
p[tail]=1;
dis[1]=0;
sta[1]=1;
long long u,i,dd;
while(head^tail)
{
head++;
u=p[head];
sta[u]=0;
for(i=first[u];i;i=bian[i].next)
{
dd=bian[i].to;
if(!exist[dd] &&dis[dd]>dis[u]+bian[i].len)
{
dis[dd]=dis[u]+bian[i].len;
if(!sta[dd])
{
sta[dd]=1;
tail++;
p[tail]=dd;
}
}
}
}
return dis[m];
}
int main()
{
freopen("lx.in","r",stdin);
freopen("lx.out","w",stdout);
n=read();
m=read();
k=read();
e=read();
long long i,j,s,t,u;
for(i=1;i<=e;i++)
{
s=read();
t=read();
j=read();
inser(s,t,j);
inser(t,s,j);
}
d=read();
for(i=1;i<=d;i++)
{
u=read();
s=read();
t=read();
for(j=s;j<=t;j++)
used[j][u]=1;
}
for(i=1;i<=n;i++)
{
for(u=1;u<=m;u++) exist[u]=0;
for(j=i;j<=n;j++)
{
for(u=1;u<=m;u++)
if(used[j][u]) exist[u]=1;
for(u=1;u<=m;u++) dis[u]=1000000000;
cost[i][j]=spfa();
}
}
// for(i=1;i<=n;i++) dp[i]=100000000;
for(i=1;i<=n;i++)
{
dp[i]=cost[1][i]*i;
for(j=1;j<i;j++)
{
if(cost[j+1][i]<1000000000)
dp[i]=min(dp[i],dp[j]+cost[j+1][i]*(i-j)+k);
}
}
cout<<dp[n];
return 0;
}