zoukankan      html  css  js  c++  java
  • 2016 Benelux Algorithm Programming Contest (BAPC 16)

    Time:2018.4.27  17:00-22:00

    Link


    A

    题意

    分析

    几何最短路,留坑


    B    solved by ym

    题意

    ym:按题意模拟即可 


    C    solved by ym

    题意

    ym:赛时czh的代码FST了,按题意模拟不断删点,实际上和拓扑排序删点相似

    #include<bits/stdc++.h>
    using namespace std;
    
    int head[300003*2],nxt[300003*2],to[300003*2],tot;
    int C,P,X,L;
    int d[200005],del[200005];
    bool vis[200005];
    
    
    void add(int u,int v)
    {
        ++tot;
        to[tot]=v;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    
    void topsort()
    {
        queue<int>q;
        q.push(L);
        vis[L]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=nxt[i])
            {
                int v=to[i];
                del[v]++;
                if(!vis[v]&&del[v]>=((d[v]+1)/2))
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d%d",&C,&P,&X,&L);
        int u,v;
        for(int i=1;i<=P;i++)
        {
            scanf("%d%d",&u,&v);
            d[u]++;
            d[v]++;
            add(u,v);
            add(v,u);
        }
        topsort();
        if(vis[X])
        {
            cout<<"leave"<<endl;
        }
        else
            cout<<"stay"<<endl;
        return 0;
    }

    D

    题意

    现有n艘船需要通过桥,但桥很累不想一直连通,所以在“闲”的时候可以不连通,但每艘船不可以等待超过30min,升/降桥会花费60s,每艘船通过花费20s,船一艘一艘的通过,给出每艘船到达桥的时间T_i,问船工作的最小时间(升降+连通) ( n<=4000,T_i<=1e5,i<j && T_i+20<=T_j )

    分析

    ym:令f_i为前艘船通过的最小时间,枚举和i一起通过的船j(j<=i),转移即可

    时间复杂度O(n^2)

    #include<bits/stdc++.h>
    using namespace std;
    
    int dp[4005],n,a[4005];
    
    int main()
    {
    
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            dp[i]=1000000+7;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        dp[1]=140;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j<=i;j++)
            {
                dp[i]=min(dp[i], dp[j-1]+120+20+a[i]-min(a[j]+1800,a[i]-(i-j)*20));
            }
        }
        printf("%d
    ",dp[n]);
        return 0;
    }

    E

    题意

    给一个n个点m条边的无向图,给出起点到终点的路径最大值,问满足路径和小于max的所有路径中每条路径的最大值最小(n<=1e4,m<=1e5,w<=1e9)

    分析

    ym:比赛时候天马行空的考虑完全图路径很多的情况==,实际上至于只需要关注每一个点和边的访问次数,便能正确得出时间复杂度,例如在有权的无向图中的单源最短路,由于每个点只会被取出一次所以时间复杂度为(VlogV),回到此题,二分答案(最短路具有单调性)最短路检查即可(边权w如果大于mid,相当于看做不选择这条边即可,在剩下的点中求最短路径)

    时间复杂度O(nlog2n)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=210000;
    priority_queue<pair<LL,int>,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
    const LL INF=1e18;
    LL dis[110000];
    int vis[110000];
    int n,m,x;
    
    int head[maxn],nxt[maxn],to[maxn],tot;
    LL w[210000];
    
    void add(int u,int v,int c)
    {
        ++tot;
        to[tot]=v;
        w[tot]=c;
        nxt[tot]=head[u];
        head[u]=tot;
    }
    
    LL dij(int limt)
    {
        for(int i=1;i<=n;i++)
            dis[i]=INF,vis[i]=0;
        dis[1]=0;
        q.push(make_pair(0,1));
        while(!q.empty())
        {
            int now=q.top().second;
            q.pop();
            if(vis[now])
                continue;
            vis[now]=1;
            for(int i=head[now];i!=0;i=nxt[i])
            {
                if (w[i]<=limt&&dis[to[i]]>dis[now]+w[i])
                {    dis[to[i]]=dis[now]+w[i];
                    q.push(make_pair(dis[to[i]],to[i]));
                }
            }
        }
        return dis[n];
    
    }
    LL dist;
    int ans;
    int check(int x)
    {
        return dij(x)<=dist;
    }
    
    int main()
    {
        scanf("%d%d%d", &n, &m,&x);
        int u,v;
        int c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,c);
            add(v,u,c);
        }
        dist=dij(1000000000);
        dist=dist*(100LL+x)/100;
        int l=1,r=1000000000;
        while (l<=r)
        {
              int mid=(l+r)/2;
              if (check(mid)) ans=mid,r=mid-1;
              else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }

    F

    题意

    分析

    几何模拟,留坑


    G

    题意

     

    分析

     ym:可做几何,待补


    H

    题意

     

    分析

    ym:爆搜剪纸,待补


    I      solved by czh&ym

    题意

    ym:按题意模拟即可


    J    solved by ym&czh

    题意

    分别给出n个学生和n个导师的二维坐标,定义两点的dis:|x1-x2|+|y1-y2|,现要一 一配对,要使最大的dis最小,问每个最大所有情况最小的dis

    分析

    ym:算法理解不深刻,只会套板子

             二分图是根据边集,不断找增广路,故可以二分答案,二分图check,即在找增广路的时候加上约束条件

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn = 100+7;
    
    int n,f[maxn],v[maxn];
    ll sx[maxn],sy[maxn],tx[maxn],ty[maxn];
    
    ll _abs(ll x){
        if(x>0) return x;
        else return -x;
    }
    
    ll dis(int i,int j){
        return _abs(sx[i]-tx[j])+_abs(sy[i]-ty[j]);
    }
    
    bool found(int x,ll mid)
    {
        for(int i=1;i<=n;i++)
        {
            if(dis(x,i)<=mid&&!v[i])
            {
                v[i]=1;
                if(f[i]==0||found(f[i],mid))
                {
                    f[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    
    bool check(ll mid)
    {
        for(int i=1;i<=n;i++)
            f[i]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++) v[j]=0;
            if(!found(i,mid))
                return false;
        }
        return true;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&sx[i],&sy[i]);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&tx[i],&ty[i]);
        bool flag=true;
        ll l=0,r=1000000000;
        while(l<r)
        {
            ll mid=(l+r)/2;
            if(check(mid))
            {
                r=mid;
            }
            else
                l=mid+1;
        }
        printf("%lld
    ",l);
        return 0;
    }

    K

    题意

    给出长度为L的圆形跑道,每S米至少放一个人,问方案数 

    分析

    ym:dp待补 


    L   solved by czh&ym

    题意

    ym:排序后检查相邻3项能否形成三角形即可


    Summary

    Ym这次表现看上去不错,,其实很惨,数据有锅,Link以Update,kattis数据正确(甚至很强,E卡我两个小时),以后比赛多读几道题,利于补题呀!!!

    Czh:

  • 相关阅读:
    广域网(ppp协议、HDLC协议)
    0120. Triangle (M)
    0589. N-ary Tree Preorder Traversal (E)
    0377. Combination Sum IV (M)
    1074. Number of Submatrices That Sum to Target (H)
    1209. Remove All Adjacent Duplicates in String II (M)
    0509. Fibonacci Number (E)
    0086. Partition List (M)
    0667. Beautiful Arrangement II (M)
    1302. Deepest Leaves Sum (M)
  • 原文地址:https://www.cnblogs.com/Deadline/p/8965852.html
Copyright © 2011-2022 走看看