hiho一下 第三十八周 二分·二分答案【二分+bfs】

本文介绍了一个基于二分搜索算法的游戏路径优化问题。玩家需要在满足燃料和弹药限制的前提下,找到从起点到敌方Boss点所需的最低索敌值。通过使用二分搜索,可以在大量路径中快速确定最优解。

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

#1139 : 二分·二分答案

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB
描述

在上一回和上上回里我们知道Nettle在玩《艦これ》,Nettle在整理好舰队之后终于准备出海捞船和敌军交战了。
在这个游戏里面,海域是N个战略点(编号1..N)组成,如下图所示

其中红色的点表示有敌人驻扎,猫头像的的点表示该地图敌军主力舰队(boss)的驻扎点,虚线表示各个战略点之间的航线(无向边)
在游戏中要从一个战略点到相邻战略点需要满足一定的条件,即需要舰队的索敌值大于等于这两点之间航线的索敌值需求。
由于提高索敌值需要将攻击机、轰炸机换成侦察机,舰队索敌值越高,也就意味着舰队的战力越低。
另外在每一个战略点会发生一次战斗,需要消耗1/K的燃料和子弹。必须在燃料和子弹未用完的情况下进入boss点才能与boss进行战斗,所以舰队最多只能走过K条航路。
现在Nettle想要以最高的战力来进攻boss点,所以他希望能够找出一条从起始点(编号为1的点)到boss点的航路,使得舰队需要达到的索敌值最低,并且有剩余的燃料和子弹。

特别说明:两个战略点之间可能不止一条航线,两个相邻战略点之间可能不止一条航线。保证至少存在一条路径能在燃料子弹用完前到达boss点。

提示:你在找什么?

输入

第1行:4个整数N,M,K,T。N表示战略点数量,M表示航线数量,K表示最多能经过的航路,T表示boss点编号, 1≤N,K≤10,000, N≤M≤100,000
第2..M+1行:3个整数u,v,w,表示战略点u,v之间存在航路,w表示该航路需求的索敌值,1≤w≤1,000,000。

输出

第1行:一个整数,表示舰队需要的最小索敌值。

样例输入
5 6 2 5
1 2 3
1 3 2
1 4 4
2 5 2
3 5 5
4 5 3
样例输出
3


代码:

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
    int to,next,w;
}pp[230000];
struct nn{
    int xx,step;
}now,qian;
int n,m,k,t;
int head[12000];
bool fafe[12000];
void ADD(int a,int b,int c,int i)
{
    pp[i].to=b;
    pp[i].w=c;
    pp[i].next=head[a];
    head[a]=i;
}
int fa(int p)
{
    queue < nn > que;
    now.step=0;
    now.xx=1;
    que.push(now);
    memset(fafe,true,sizeof(fafe));
    fafe[1]=false;int a,b;
    while (!que.empty())//bfs
    {
        qian=que.front();
        que.pop();
        if (qian.step>k)
            return false;
        if (qian.xx==t)
            return true;
        for (int i=head[qian.xx];i!=-1;i=pp[i].next)
        {
            if (fafe[pp[i].to]&&pp[i].w<=p)
            {
                now.step=qian.step+1;
                now.xx=pp[i].to;
                fafe[pp[i].to]=false;
                que.push(now);
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&t);
    int a,b,c;
    int l=0,r=0,M;
    for (int i=0;i<=n;i++)
        head[i]=-1;
    for (int i=0;i<m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        r=max(r,c);
        ADD(a,b,c,i*2);
        ADD(b,a,c,i*2+1);
    }
    int ans;
    while (l<=r)//二分
    {
        M=(l+r)>>1;
        if (fa(M))
        {
            r=M-1;
            ans=M;
        }
        else
            l=M+1;
    }
    printf("%d\n",ans);
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值