hrbust 1687/哈理工oj 1687 买房子【二维最短路+SPFA】

本文介绍了一道经典的算法问题,即如何在一个带有双向边的图中,通过遍历边来收集足够的金币,并找到到达目标节点所需的最短时间。文章详细解析了问题背景及输入输出要求,并提供了一个高效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

买房子

Time Limit: 1000 MS

Memory Limit: 32768 K

 

Total Submit: 13(6 users)

Total Accepted: 4(4 users)

Rating: 

Special Judge: No

 

Description

小W是一个商人并且希望购买一个房子,他发现没有足够的金币去买它。
所以他需要挣足够的金币。在他所在城镇附近有许多的城镇。
城镇之间是双向道路(一个城镇可以连接到本身)。
当他经过一条路时,他将通过某种途径获得10金币并且消耗一定时间。
小W需要K金币。所以小W需要收集至少K金币。 
城镇编号从1到N,小W起始城镇编号为S,小W希望在T城镇购买房子。
小W希望尽可能早的购买这个房子。请你帮他计算最少需要的时间。

Input

输入的第一行是一个整数T,表示一共有T组测试数据;
对于每组测试数据第一行是两个整数N (1<=N<=5000), M (0<=M<=100000)。分别代表城镇的数量和道路的数量。
接下来是三个整数A B C(1<=A,B<=N;1<=C<=100)意味着A城镇和B城镇之间存在一个道路,并通过这条路将花费C时间。
最后一行是三个整数S T K(1<=S,T<=N;0<=K<=500)如题目描述。

Output

对于每组测试数据,输出购买房子所需要的最少时间,如果不可能则输出-1,每组输出占一行。

Sample Input

2
4 4
1 2 1
2 3 2
1 3 100
3 4 1
1 3 50
3 0
1 2 50

Sample Output

7
-1

Author

陈禹@HRBUST



思路:

1、二维最短路,设定dis【i】【j】表示当前走到了i点,而且手上有j金币的最小权值花费。那么理所应当,vis【i】【j】其中ij的含义也是想通的。


2、SPFA求最短路,松弛方程式为:dis【v】【j】=min(dis【v】【j】,dis【u】【j-10】+w【u】【v】);


3、如果我们直接这样求的话,我们最终要在dis【T】【kk-尽可能大】,那么这个尽可能大到底应该确定值为多少呢?其实实际结果是确定值到1000的话也会超时,那么就别想更大的情况了。


4、那么要怎样解决超时问题呢?当j>kk的时候,其实我们直接领j=kk即可。这样,我们就能将所有可以的情况归一,相对的减少了很多的操作。


AC代码:


#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
    int u,val;
}now,nex;
int head[100000];
struct EdgeNode
{
    int to;
    int w;
    int next;
} e[100000];
bool vis[5005][1005];
int dis[5005][1005];
int n,m,cont;
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void SPFA(int ss,int tt,int kk)
{
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=1000;j++)
        {
            dis[i][j]=0x3f3f3f3f;
            vis[i][j]=0;
        }
    }
    dis[ss][0]=0;
    vis[ss][0]=1;
    queue<node>s;
    now.u=ss;
    now.val=0;
    s.push(now);
    while(!s.empty())
    {
        now=s.front();
        s.pop();
        int u=now.u;
        int val=now.val;
        vis[u][val]=0;
        for(int j=head[u];j!=-1;j=e[j].next)
        {
            int w=e[j].w;
            int v=e[j].to;
            nex.u=v;nex.val=now.val+10;
            if(nex.val>kk)nex.val=kk;
            if(dis[nex.u][nex.val]>dis[now.u][now.val]+w)
            {
                dis[nex.u][nex.val]=dis[now.u][now.val]+w;
                if(vis[nex.u][nex.val]==0)
                {
                    vis[nex.u][nex.val]=1;
                    s.push(nex);
                }
            }
        }
    }
    if(dis[tt][kk]==0x3f3f3f3f)
    {
        printf("-1\n");
    }
    else
    printf("%d\n",dis[tt][kk]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cont=0;
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=0; i<m; i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        int s,t,k;
        scanf("%d%d%d",&s,&t,&k);
        SPFA(s,t,k);
    }
}




资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值