zoukankan      html  css  js  c++  java
  • hihocoder hiho第38周: 二分·二分答案 (二分搜索算法应用:二分搜索值+bfs判断可行性 )

    题目1 : 二分·二分答案

    时间限制: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 <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <ctype.h>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #define N 10000+10
    
    using namespace std;
    
    struct node
    {
    	int v;
    	int w;
    };
    int n, m, kk, boss;
    
    vector<node>q[100000+10];
    
    bool bfs(int k)
    {   //起点编号为1
        int fa[N]; memset(fa, 0, sizeof(fa));
        fa[1]=kk;
        bool vis[N]; memset(vis, false, sizeof(vis));
        queue<int>p;
        p.push(1); vis[1]=true;
        while(!p.empty())
        {
            int cur=p.front(); p.pop();
            for(int i=0; i<q[cur].size(); i++)
            {
                int dd=q[cur][i].v;
                int ff=q[cur][i].w;
    
                if(vis[dd]==false &&ff<=k )
                {
                    vis[dd]=true;
                    fa[dd]=fa[cur]-1;
                    if(dd==boss && fa[dd]>=0 )
                    {
                        return true;
                    }
                    p.push(dd);
                }
            }
        }
        return false;
    }
    
    
    int main()
    {
    
    	scanf("%d %d %d %d", &n, &m, &kk, &boss);
    	int i, j, k;
        int u, v, w;
        node t;
        int ma=-1, mi=21000000000;
    	for(i=0; i<m; i++)
    	{
    		scanf("%d %d %d", &u, &v, &w);
    		ma=max(ma, w); mi=min(mi, w);
    
    		t.v=v; t.w=w;
    		q[u].push_back(t);
    		t.v=u; t.w=w;
    		q[v].push_back(t); //
    	}
        //二分枚举最大和最小之间的区间
        i=mi; j=ma; int mid;
        int pos;
        while(i<=j)
        {
            mid=(i+j)/2;
            if(bfs(mid)==true )
            {
                if(bfs(mid-1)==false)
                {
                    pos = mid; break;
                }
                else
                    j=mid;
            }
            else
                i=mid;
        }
    	printf("%d
    ", pos);
    	return 0;
    }
    
  • 相关阅读:
    WEEK
    更新yum源
    Centos6.9安装Mysql5.7.18
    gitlab使用
    gitlab安装
    git客户端
    服务器端配置
    错误问题
    服务器端
    01找出数组中重复的数
  • 原文地址:https://www.cnblogs.com/yspworld/p/4361100.html
Copyright © 2011-2022 走看看