zoukankan      html  css  js  c++  java
  • POJ 3343 Against Mammoths(二分匹配+二分答案)

    题意:(这个题目好长~~~)有n个人类星球,m个外星球,每个星球上开始sh艘飞船,之后每年会生产p艘飞船,人类想要战胜所有的外星球,每个人类星球和每个外星球的距离已知(需要耗费k年),比如在a年初,人类星球H向外星球A宣战,那么人类会带上sh+p*a艘飞船进攻,经过k年后到达外星球,这时外星球飞船的数量为sh'+p'*(a+k),如果这时人类飞船的数量>=外星球飞船的数量,那么就会战胜这个外星球,每个人类星球只能攻击一个外星球,一个外星球只能被一个人类星球攻击,问最少需要多少年人类才能全部战胜所有的外星球。

    思路:由于人类星球和外星球是一一对应的关系,所以自然想到了二分匹配,但是时间是未知的,所以可以通过二分答案的途径来确定时间,对于每个时间k检测人类是否能打败所有的外星球.....输出最小值就可以了,由于答案是从1<<31-1开始二分的,所以计算过程中可能会超出int范围,故要注意__int64类型的转换。

    #include <iostream>
    #include
    <cstdio>
    #include
    <algorithm>
    #include
    <memory.h>
    #include
    <cmath>
    #include
    <bitset>
    #include
    <queue>
    #include
    <vector>
    using namespace std;

    const int BORDER = (1<<26)-1;
    const int MAXSIZE = 37;
    const int MAXN = 300;
    const int INF = 0x6ffffff;
    #define CLR(x,y) memset(x,y,sizeof(x))
    #define ADD(x) x=((x+1)&BORDER)
    #define IN(x) scanf("%d",&x)
    #define OUT(x) printf("%d\n",x)
    #define MIN(m,v) (m)<(v)?(m):(v)
    #define MAX(m,v) (m)>(v)?(m):(v)
    #define ABS(x) ((x)>0?(x):-(x))

    typedef
    struct{
    int v,next;
    int val;
    }Edge;
    typedef
    struct{
    int sh;
    int p;
    }Node;
    int n,m,ans,index;
    int dist[MAXN][MAXN],net[MAXN],pre[MAXN];
    bool visit[MAXN];
    Edge edge[MAXN
    *MAXN];
    Node hum[MAXN],mam[MAXN];

    void add_edge(const int& u,const int& v)
    {
    edge[index].v
    = v;
    edge[index].next
    = net[u];
    net[u]
    = index;
    ++index;
    }
    bool _check(const Node& a,const Node& b,const int& dis,const int& limit)
    {
    if(limit < dis)
    return false;
    if(a.sh >= b.sh+(__int64)dis*b.p)
    return true;
    if(a.sh+(__int64)(limit-dis)*a.p >= b.sh+(__int64)limit*b.p)
    return true;
    return false;
    }
    int init()
    {
    index
    = 0;
    ans
    = -1;
    CLR(net,
    -1);
    CLR(pre,
    -1);
    return 0;
    }
    int input()
    {
    int i,j,a,b,val;
    for(i = 0; i < n; ++i)
    scanf(
    "%d%d",&hum[i].sh,&hum[i].p);
    for(i = 0; i < m; ++i)
    scanf(
    "%d%d",&mam[i].sh,&mam[i].p);
    for(i = 0; i < n; ++i)
    for(j = 0; j < m; ++j)
    {
    scanf(
    "%d",&dist[i][j]);
    }
    return 0;
    }
    bool dfs(const int& u)
    {
    int i,v;
    for(i = net[u]; i != -1; i = edge[i].next)
    {
    v
    = edge[i].v;
    if(!visit[v])
    {
    visit[v]
    = true;
    if(pre[v] == -1 || dfs(pre[v]))
    {
    pre[v]
    = u;
    return true;
    }
    }
    }
    return false;
    }
    int make_graph(const __int64& limit)
    {
    int i,j,val,u,v,tmp;
    index
    = 0;
    CLR(net,
    -1);
    CLR(pre,
    -1);
    for(i = 0; i < n; ++i)
    for(j = 0; j < m; ++j)
    {
    if(_check(hum[i],mam[j],dist[i][j],limit))
    add_edge(i,j);
    }
    return 0;
    }
    int work()
    {
    int i,j,tmp;
    __int64 b_low
    = 0;
    __int64 b_high
    = (1<<31)-1;
    __int64 b_mid;
    while(b_low <= b_high)
    {
    b_mid
    = (__int64)(b_low+b_high)>>1;
    make_graph(b_mid);
    tmp
    = 0;
    for(i = 0; i < n; ++i)
    {
    CLR(visit,
    0);
    if(dfs(i))
    ++tmp;
    }
    if(tmp == m)
    {
    ans
    = b_mid;
    b_high
    = b_mid - 1;
    }
    else
    b_low
    = b_mid + 1;
    }
    if(ans == -1)
    printf(
    "IMPOSSIBLE\n");
    else
    OUT(ans);
    return 0;
    }
    int main()
    {
    while(scanf("%d%d",&n,&m))
    {
    if(!n && !m)
    break;
    init();
    input();
    work();
    }
    return 0;
    }
  • 相关阅读:
    原型与原型链
    数据类型与计算
    JavaScript实现版本号比较
    vue依赖
    vue
    面试经验
    第十一节课 课堂总结
    第十一次作业
    第十课课堂总结
    第十次作业
  • 原文地址:https://www.cnblogs.com/lvpengms/p/1714083.html
Copyright © 2011-2022 走看看