spfa+dp
这道题题目有点别扭,不是很懂。
最后问oywb才懂。
其实是每一天都走一辆船,但后一天和前一天走的不同,那就要加上k的费用。
思路:
1.先用一个mindis[i][j]表示第i天走到第j天怎样走才是最优的。 (单一种方案来走)
2.之后用一个f数组存最优解
f[i]=min(f[i],f[j-1]+mindis[i][j]*(i-j+1)+k)
单一方案走(i-j+1)天和改路线的费用
Code:
/**************************************************************
Problem: 1003
User: wohenshuai
Language: C++
Result: Accepted
Time:40 ms
Memory:1344 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
int x,y,d,next;
}a[1100]; int len,first[110];
int n,m,k,e,D;
void ins(int x,int y,int d)
{
len++; a[len].x=x; a[len].y=y; a[len].d=d;
a[len].next=first[x]; first[x]=len;
}
int st[110],ed[110],point[110];
void Input()
{
scanf("%d%d%d%d",&n,&m,&k,&e);
len=0; memset(first,0,sizeof(first));
for(int i=1;i<=e;++i)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
ins(x,y,d); ins(y,x,d);
}
scanf("%d",&D);
for(int i=1;i<=D;++i)
scanf("%d%d%d",&point[i],&st[i],&ed[i]);
}
int day[110];
void prework(int day1,int day2)
{
memset(day,1,sizeof(day));
for(int i=1;i<=D;i++)
{
if((st[i]>day2)||(ed[i]<day1)) continue;
day[point[i]]=0;
}
}
queue<int>Q;
bool v[110];
int dis[110];
int Spfa()
{
while(!Q.empty()) Q.pop();
memset(v,0,sizeof(v));
v[1]=true; Q.push(1);
memset(dis,63,sizeof(dis)); dis[1]=0;
while(!Q.empty())
{
int x=Q.front();
for(int k=first[x];k;k=a[k].next)
{
int y=a[k].y;
if(day[y]&&(dis[y]>dis[x]+a[k].d))
{
dis[y]=dis[x]+a[k].d;
if(!v[y])
{
v[y]=true;
Q.push(y);
}
}
}
Q.pop(); v[x]=false;
}
return dis[m];
}
int f[110];
int minDis[110][110];
void Solve()
{
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
prework(i,j);
minDis[i][j]=Spfa();
}
}
memset(f,63,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
if(f[j-1]<99999999&&minDis[j][i]<99999999)
{
f[i]=min(f[i],f[j-1]+minDis[j][i]*(i-j+1)+k);
}
}
}
}
void Output()
{
printf("%d\n",f[n]-k);
}
int main()
{
Input();
Solve();
Output();
return 0;
}