Papa的魔法靴子 (原BZOJ 2662)

在Papa所在的魔法大陆上,有N个城市,M条双向的道路。大魔法师Papa准备开始休假了,在1号城市的他,准备去第N号城市旅行,他想尽快的到达N市,这样他就可以花更多是时间去和老朋友们见面。

 

Papa有一双魔法靴子,他的魔法靴子可以施法K次,每次施法可以使他的速度快一倍。这也就是说,在通过某条路径时,我们可以选择施一次法,这样,我们通过这一条道路的时间就可以减少到原先的一半。需要注意的是: 
  1. 在一条道路上最多只能施法一次。 
  2. 每次施法只在一条道路上起作用。 
  3. 没有必要把K次施法都用完。 

给定以上的信息,你的任务是:求出在可以使用这不超过 K 次的魔法靴子之情形下,从城市1 到城市N最少需要多长时间。

 

Input
第一行包含三个整数:N、M、K。 
接下来 M 行,每行包含三个整数:Ai、Bi、Ti,表示存在一条 Ai与 Bi之
间的双向道路,在不施法的前提下,通过它需要 Ti的时间。

Output

输出一个整数,表示从1 号城市到 N号城市的最小用时。

Sample Input

4 4 1

1 2 4

4 2 6

1 3 8

3 4 8

Sample Output

7

【样例1 解释】

  在不施法时,最短路为 1->2->4,总时间为 10。现在我们可以施法一次,那么我们将通过 2->4 这条道路的时间减半,此时总时间为7。

HINT

对于100%的数据:1  ≤  K  ≤  N ≤  50,M  ≤  1000。 
  1≤  Ai,Bi ≤  N,2 ≤  Timei  ≤  2000。 
为保证答案为整数,保证所有的 Timei均为偶数。 
所有数据中的无向图保证无自环、重边,且是连通的。


 

定义两个结构体:

struct Edge{  //存边,不解释

  int from,to,val,next;  

}edge[MX];

struct Sta{  //状态,到某位置时的花费

   int arr,cos; 

};

我们用一个二维数组 dis[i][j] 表示到 i 位置花费 j 个代价,同时以状态建队:queue<Sta> q;

SPFA:(分两种情况)

1.不施法  

用了 j 次法力到达 i  -> 更新 -> 入队

2.施法

判断 j < t(是否还可以施法)-> 更新 -> 入队

 

代码如下

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,dis[101][101],first[101];
bool vis[101][101];

struct Edge{
    int to,val,next;
}edge[2002];
struct Sta{
    int pos,cos;
};

int cnt;
void add(int from,int to,int val)
{
    edge[++cnt].to=to;
    edge[cnt].val=val;
    edge[cnt].next=first[from];
    first[from]=cnt;
}

void Spfa()
{
    queue<Sta> q;
    memset(dis,0x3f,sizeof(dis));
    dis[1][0]=0;
    vis[1][0]=1;    
    q.push((Sta){1,0});
    
    while(!q.empty())
    {
        Sta cur=q.front();q.pop();
        int pos=cur.pos;
        int cost=cur.cos;
        for(int i=first[pos];i;i=edge[i].next)
        {
            int to=edge[i].to;
            if(dis[pos][cost]+edge[i].val<dis[to][cost])
            {
                dis[to][cost]=dis[pos][cost]+edge[i].val;
                if(!vis[to][cost]){
                    vis[to][cost]=1;
                    q.push((Sta){to,cost});
                }
            }
        }
        if(cost<k) {
            for(int i=first[pos];i;i=edge[i].next)
            {
                int to=edge[i].to;
                if(dis[pos][cost]+(edge[i].val>>1) < dis[to][cost+1])
                {
                    dis[to][cost+1]=dis[pos][cost]+(edge[i].val/2);
                    if(!vis[to][cost+1]){
                        vis[to][cost+1]=1;
                        q.push((Sta){to,cost+1});
                    }
                }    
            }
        }
    }
    int ans=0x3f3f3f3f;
    for(int i=0;i<=k;++i) ans=min(ans,dis[n][i]);
    printf("%d",ans);
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;++i){
        int from,to,val;
        scanf("%d%d%d",&from,&to,&val);
        add(from,to,val);
        add(to,from,val);
    }
    Spfa();
    return 0;
}

 

posted @ 2018-07-30 13:00  qseer  阅读(204)  评论(0编辑  收藏  举报