Mr. Rito Post Office
你是一个为远程邮局邮局工作的程序员。你住的地区由几个岛屿组成。每个岛屿都有一个或多个港口城镇。除此之外,还有其他城镇和村庄。为了从一个岛到另一个岛,你必须使用一艘船。陆地道路可用于绕过一个岛屿,但使用海路可能会更快。
随着近年来邮局的私有化,邮政派遣员工的人事安排在全国范围内进行,以减少开支。远程邮局的邮局也不例外,因此,只有托伊先生成为邮差。由于邮局负责收集和交付的区域非常广泛,因此由一个人收集和分发是一项艰巨的工作。所以,Toi先生问你如何有效地做到这一点。
你的工作是编写一个程序,当Tobi先生获得城镇和村庄的接送订单时,可以找到最短路径。
Toi先生将永远无法按规定的顺序进行收集和交付工作。但是,从一个城镇或村庄迁移到另一个城镇或村庄时,可以通过其他城镇和村庄。此外,Toji先生还有一艘船绕着岛屿转。
例如,考虑到A镇的选择和交付顺序,B镇,C村,任何城镇或村庄都可以从A镇到B镇。在这个时候,但它可能是通过村C,以保护集散顺序,进行集散去一次B镇后,必须进行再次集散访村C.另外,如果您从A镇乘船前往B镇,然后使用陆路从B镇前往C村,则您将离开B镇。因此,如果你想下一次使用大海,你需要返回B镇。
在某些情况下,有必要收集和分发到多个城镇和村庄。例如,可以给出A镇,B村,C镇,B村的收集订单。此时,如果您在没有从A镇的B村追踪的情况下前往C镇,则您不能在城镇C拣货并突然出货。这是因为第一个B村的接送并没有结束。即使集散走访了B村完成了镇C中的收集和交付后,并不意味着结束了收集和第一轮村B的交付
Toji先生在开始时在某个港口城市有一艘船。由于Toi先生是一名资深人士,您可以忽略除旅行时间之外的收集和交付工作所需的时间。此外,它是唯一的一次,直到在城镇或村庄结束的集散作业完成的问题,去邮局船返回到原来位置的时间可能不会考虑。
输入
输入由多个数据集组成。每个数据集的格式如下。
N M
x 1 y 1 t 1 sl 1
x 2 y 2 t 2 sl 2
...
xM y M t M slM
[R
z1 z2 ... zR
数据集中的所有输入项都是非负整数。该行中输入项目的分隔符是一个空格。
第一行指定陆地和海洋网络的大小。
N(2≤N≤200)是城镇或村庄的数量。每个城镇或村庄都分配一个从1到N的唯一编号。 M(1≤M≤10000)是陆地和海洋的总数。
第1 + M行的第二行是对陆地或海路的描述。 xi和yi(1≤xi,yi≤N)表示两端的城镇或村庄的数量。 ti(1≤ti≤1000)表示陆地或海路的行程时间。 sli是'L'或'S',L是陆路,S是海路。
可能有两个或更多直接连接两个城镇和村庄的陆路或海路。每条陆地或海路都是双向的,即它可以向任何方向移动。
M + 2线上的R(1≤R≤1000)表示Toji先生处理的收集目的地和递送目的地的数量。 M + 3行,收集和城镇和数字字(1≤滋≤N)的村庄的传送目的地设置r个在收集和传递顺序。
在最初的状态下,Toji先生和这艘船都位于港口城镇z1。从最初的状态,你总是可以以某种方式移动到你选择和交付的城镇和村庄。
输入的结尾由包含由空白分隔的两个零的单行表示。
产量
对于每个输入数据集,找出Toji先生在给定的取件订单中在城镇和村庄周围旅行所需的最短行程时间,并将其输出到一条线上。
示例输入
3 3
1 2 5 L
1 2 7 S
2 3 11 S
3
1 2 3
5 5
1 2 15 L
2 3 10 L
4 5 7 L
1 3 30 S
3 4 100 S
五
1 3 5 4 1
0 0
样本输入的输出
18
269
题目方程很好推出来,f[i][j]表示现在处于第i个快递点而船在j点时的最小花费,预处理出来纯陆地最短路和纯水路最短路,由于游历的顺序固定所以第i个点直接向第i+1个转移即可。
一直WA的原因,一是数组开小了,最多游历1000个点并不一定是200,可能一个点多次。。。还有我的floyd写错了。。循环变量反了。。最后inf设置的不合理貌似中间爆了,吃完饭重新写才A。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL f[][],e1[][],e2[][],inf;
int a[];
int main(){
int n,m,i,j,k,u,r,v;
char str[];
LL w;
while(cin>>n>>m){
if(n==&&m==) break;
memset(e1,0x1,sizeof(e1));
memset(e2,0x1,sizeof(e2));
memset(f,0x1,sizeof(f));
for(i=;i<=n;++i)e1[i][i]=e2[i][i]=;
inf=f[][];
while(m--)
{
scanf("%d%d%lld",&u,&v,&w);
scanf("%s",str);
if(str[]=='L'){
e1[u][v]=e1[v][u]=min(e1[u][v],w);
}
else{
e2[u][v]=e2[v][u]=min(e2[u][v],w);
}
}
for(k=;k<=n;++k){
for(i=;i<=n;++i){
for(j=;j<=n;++j){
e1[i][j]=min(e1[i][j],e1[i][k]+e1[k][j]);
e2[i][j]=min(e2[i][j],e2[i][k]+e2[k][j]);
}
}
}
scanf("%d",&r);
for(i=;i<=r;++i) scanf("%d",a+i);
for(i=;i<=n;++i) f[][i]=min(f[][i],
e2[a[]][i]+e1[i][a[]]); for(i=;i<r;++i){
for(j=;j<=n;++j){
if(f[i][j]!=inf){
f[i+][j]=min(f[i+][j],f[i][j]+e1[a[i]][a[i+]]);
for(k=;k<=n;++k){
f[i+][k]=min(f[i+][k],f[i][j]+e2[j][k]+e1[a[i]][j]+e1[k][a[i+]]);
}
}
}
} LL ans=inf;
for(i=;i<=n;++i)ans=min(ans,f[r][i]);
cout<<ans<<endl;
}
return ;
}