hihocoder 二分·二分答案【二分搜索,最大化最小值】

题目

这道题做了几个小时了都没有做出来,首先是题意搞了半天都没有弄懂,难道真的是因为我不打游戏所以连题都读不懂了?

反正今天是弄不懂了,过几天再来看看。。。

题意:一个人从1点出发到T点去打boss,这个人有两个属性值,防御值和战斗值,这两个值成反比,为了打赢boss我们要使战斗值最大,于是乎防御值就要最低,但是也不能太低,于是乎这个界限在哪,这就是我们要求的。每条路上都有一个索敌值,防御值必须>=索敌值 才能通过。从1点到T点有很多条通路,我们要找的是:这每一条通路中索敌值最大的中索敌值最小的,感觉这句话有点绕,具体解释看下图:

1号节点是起点,5号是终点,从1到5有三条通路:1->2->5; 1->3->5; 1->4->5; 对应路径中最长的路段长度分别是:3;5;4;因此在{3,5,4}中最小值3是正确值。

所以这道题是用二分求,最大化最小值。

#include <bits/stdc++.h>
using namespace std;

int n,m,k,t;
const int Max = 10005;
int vis[Max];

struct edge{
    int x,w;
};
vector<edge> v[Max];

int bfs(int dis)
{
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(1);
    while(!q.empty())
    {
        int cur = q.front();
        q.pop();
        if(cur==t) return true;
        if(vis[cur]==k)
            continue;
        int l = v[cur].size();
        for(int i=0;i<l;i++)
        {
            int tmp = v[cur][i].x;
            if(vis[tmp]||v[cur][i].w>dis)
                continue;
            vis[tmp]=vis[cur]+1;
            q.push(tmp);
        }
    }
    return false;
}

int main()
{
    int a,b,c;
    while(~scanf("%d%d%d%d",&n,&m,&k,&t))
    {
        int a,b,c,maxn=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            edge tmp;
            tmp.x = b; tmp.w = c;
            v[a].push_back(tmp);
            tmp.x = a;
            v[a].push_back(tmp);
            maxn = max(maxn,c);
        }
        int mid,l=0,r=maxn;
        while(l<=r)
        {
            mid = (l+r)/2;
            if(bfs(mid)){
                r=mid-1;
            }else{
                l=mid+1;
            }
        }
        printf("%d\n",l);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qie_wei/article/details/81122241