zoj1232Adventure of Super Mario

#include<iostream>
#include<queue>
#include<algorithm>
#include<stdio.h>
#include<cstring>
using namespace std;
/*题意:马里奥要从A+B出的城堡走到1处的村庄,途中他可以使用boot,从任意i处到达j处,但是i与j的
距离不能超过L,且使用boot的次数不能多于K次,而且在使用时 遇到城堡就要停下来,而且只能在村庄
或城堡开始或停止使用boot,求从A+B到1所用的最短时间
*/
int A,B,M,L,K,ANS;
const int INF=100000000;
int zero[105][105],d[105][105],g[101][101], inq[101][11];
//inq[i][k]表示从A+B走到i处且用boot k次所用的最短时间,zero[i][j]表示i,j之间是否有0路
 
struct node
{
    int v,num,time;//v目前所在点,num所用boot次数,time所耗时间
    node(int _v,int _num,int _time):v(_v),num(_num),time(_time){};
    friend bool operator <(const node &a,const node &b)
    {
        if(a.num!=b.num)return a.num>b.num;
        return a.time>b.time;
    }
};
void add_zero()
{
    //用floyd算出各点的最短距离,以判断可否加0路
    for(int k=1;k<=A;k++)//城堡不能成为中转站,因为boot失效
        for(int i=1;i<=A+B;i++)
            for(int j=1;j<=A+B;j++)
            {
                if(d[i][j]>d[i][k]+d[k][j])
                    d[i][j]=d[i][k]+d[k][j];
            }
         
    for(int i=1;i<=A+B;i++)
        for(int j=1;j<=A+B;j++)
            if(d[i][j]<=L){zero[i][j]=1;zero[j][i]=1;}//可以用boot 
}
void Dij()
{
    priority_queue <node> pq;
    pq.push(node(A+B,0,0));
     
    for(int i=1;i<=A+B;i++)
        for(int j=0;j<=K;j++)
            inq[i][j]=INF;
    int done[101][11];//done[i][k]表示用k次boot到i处已经算过(已是最优)
    memset(done,0,sizeof(done));
     
    while(!pq.empty())
    {
        node t=pq.top();
        pq.pop();
        done[t.v][t.num]=1;
        if(t.num>K)continue;
        if(t.num<=K&&t.v==1&&t.time<ANS){ANS=t.time;continue;}
        if(t.num<=K&&t.v==1&&t.time>=ANS)continue;
        if(t.num<=K&&t.v!=1&&t.time>=ANS)continue;
        for(int i=A+B;i>=1;i--)
        {
            if((g[t.v][i]!=INF||zero[t.v][i]))//如果有路可以走
            {
                if(!done[i][t.num]&&g[t.v][i]!=INF&&t.time+g[t.v][i]<inq[i][t.num])
                {
                    inq[i][t.num]=t.time+g[t.v][i];
                    pq.push(node(i,t.num,t.time+g[t.v][i]));
                }
                if(!done[i][t.num+1]&&zero[t.v][i]&&t.time<inq[i][t.num+1])
                {
                    inq[i][t.num+1]=t.time;pq.push(node(i,t.num+1,t.time));
                }
 
            }
        }
    }
}
void set()//各种初始化
{
    for(int i=1;i<=A+B;i++)
        for(int j=1;j<=A+B;j++)
        {d[i][j]=INF;g[i][j]=INF;}
    memset(zero,0,sizeof(zero));
    for(int i=1;i<=A+B;i++)
       for(int j=0;j<=K;j++)
            inq[i][j]=INF;
    ANS=INF;
}
int main()
{
    int cas,a,b,c;
    cin>>cas;
    while(cas--)
    {
       scanf("%d%d%d%d%d",&A,&B,&M,&L,&K);
       set();
       for(int i=0;i<M;i++)
       {
           scanf("%d%d%d",&a,&b,&c);
           g[a][b]=c,g[b][a]=c;
           d[a][b]=c;d[b][a]=c;
       }
       add_zero();
       Dij();
       printf("%d\n",ANS);
    }
 
}
posted on   4.5.6  阅读(214)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
阅读排行:
· DeepSeek V3 两周使用总结
· 回顾我的软件开发经历(1)
· C#使用yield关键字提升迭代性能与效率
· 低成本高可用方案!Linux系统下SQL Server数据库镜像配置全流程详解
· 4. 使用sql查询excel内容
点击右上角即可分享
微信分享提示