题目描述
某天,哈利•波特准备去拯救 Super Swamuel 星球上的生灵。该星球上有七种不同的地形,依次分别是:石子路、森林、草地、山地、雪地、沼泽和沙漠。分别用数字 1~7 来表示,穿越这七种地形需要的时间分别用 h1~h7 表示。
任意两个城市之间都存在至少一条通路,而且任意两个直通的城市之间都只存在一种地形。哈利•波特穿越地形 u 所需要的时间与该地形的区域大小无关,而与地形 u 的区域中是否有魔法石有关。如果地形 u 的区域中没有魔法石,哈利•波特需要花费 hu 的时间能穿越该地区;如果他有魔法石,则只要花一半的时间(hu/2)就能穿越地形 u。这里 hu/2 用整除法。
已知没有魔法石的情况下穿越七种地形需要的时间分别如下表格:
地形名称 | 石子路 | 森林 | 草地 | 山地 | 雪地 | 沼泽 | 沙漠 |
地形编号(i) | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
穿越时间(hi) | 2 | 6 | 4 | 8 | 6 | 10 | 14 |
哈利•波特将从城市 i 出发到城市 j 去伸张正义,请你帮他寻找出最快的路线。
输入格式
第一行有七个整数 s1~s7 ,分别表示七种地形中是否有魔法石,su=0 表示地形 u 的区域中没有魔法石;su=1 表示地形 u 的区域中有魔法石。su ∈{0,1}
第二行有两个正整数,分别是起点 i 的编号和终点 j 的编号。
第三行有一个正整数 m(m≤10000),表示以下有 m 对直接相连的城市。
随后 m 行,每行三个正整数 i,j,k,分别是城市 i 与城市 j 之间连通,这两个城市之间的地形是 k,其中:0<i,j≤1000,k∈{1,2,3,4,5,6,7} ,地形编号意义请参考“题目描述”中的表格。
输出格式
输出一个整数,即穿越起点城市 i 与终点城市 j 之间的地形需要的最短时间。
样例数据 1
输入
0 1 0 0 0 0 0
1 4
4
1 2 1
1 3 1
2 4 2
3 4 3
输出
5
备注
【样例说明】
从路径 1→2→4 穿越,需要的最短时间是:2+(6/2)=5
分析
就是一个最短路的板子题,我这里用的是迪杰斯特拉+堆优化
代码
#include<bits/stdc++.h>
#define in read()
#define N 1009
#define M 20009
using namespace std;
inline int read(){
char ch;int res=0;
while((ch=getchar())<'0'||ch>'9');
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return res;
}
int h[8]={2,6,4,8,6,10,14};
int head[N],nxt[M],w[M],to[M],cnt=0;
int sta,end,m;
void add(int x,int y,int z){
nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
nxt[++cnt]=head[y];head[y]=cnt;to[cnt]=x;w[cnt]=z;
}
priority_queue<pair<int,int> > q;
int dis[1009];
void dij(int st){//最短路板子
memset(dis,0x3f3f3f3f,sizeof(dis));
q.push(make_pair(st,0));dis[st]=0;
while(!q.empty()){
int u=q.top().first;
int d=q.top().second;
d=-d;
q.pop();
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
if(dis[v]>d+w[e]){
dis[v]=d+w[e];
q.push(make_pair(v,-dis[v]));//存负的,大根堆变小
}
}
}
}
int main(){
int i,j,k,x,y,z;
for(i=0;i<7;++i){
k=in;
if(k==1) h[i]/=2;
}
sta=in;end=in;m=in;
for(i=1;i<=m;++i){
x=in;y=in;z=in;//读入的z是从1~7,而我是用0~6来存储的
add(x,y,h[z-1]);
}
dij(sta);
printf("%d",dis[end]);
return 0;
}