zoukankan      html  css  js  c++  java
  • Gym -102007 :Benelux Algorithm Programming Contest (BAPC 18) (寒假自训第5场)

    A .A Prize No One Can Win

    题意:给定N,S,你要从N个数中选最多是数,使得任意两个之和不大于S。

    思路:排序,然后贪心的选即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    ll a[maxn];
    int main()
    {
        int N,ans; ll M;
        scanf("%d%lld",&N,&M);
        rep(i,1,N) scanf("%lld",&a[i]);
        sort(a+1,a+N+1);
        ans=1;
        rep(i,2,N){
            if(a[i]+a[i-1]<=M) ans=i;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    B .Birthday Boy

    题意:给出N个人的生日,让你选择一天,使得这一天的前一个生日距离它最远,如果有多个一样的,有点选择10月27之后的

    思路:模拟即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    int Y[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int vis[1000],tot;
    int mp[13][32],C[13][32],A[1000],B[1000];
    int main()
    {
        int N,y,d,ansx=1,ansy=1,ans=-1;char c[20];
        scanf("%d",&N);
        rep(i,1,N){
            scanf("%s%d-%d",c+1,&y,&d);
            mp[y][d]=1;
        }
        rep(i,1,12)
         rep(j,1,Y[i]){
            tot++; A[tot]=i; B[tot]=j; C[i][j]=tot;
            if(mp[i][j]) vis[tot]=1;
        }
        rep(i,1,tot) vis[i+tot]=vis[i],A[i+tot]=A[i],B[i+tot]=B[i];
        rep(i,tot,tot+tot-1) {
            if(vis[i]) continue;
            int j=i; while(j-1>=i-tot+1&&!vis[j-1]) j--;
            if(i-j>ans){
                ans=i-j,ansx=A[i],ansy=B[i];
            }
            else if(i-j==ans&&C[ansx][ansy]<=C[10][27]&&C[A[i]][B[i]]>C[10][27]) ansx=A[i],ansy=B[i];
        }
        printf("%02d-%02d
    ",ansx,ansy);
        return 0;
    }
    View Code

    C .Cardboard Container

    题意: 给定N个1*1*1的盒子,让你用最小的表面积把它包起来.

    思路: 枚举长和宽和高(因子)即可.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=100+10;
    const int inf=1000000000;
    int main()
    {
        int v;
        cin>>v;
        ll ans=inf;
        for(int i=1;i<=v;i++){
            if(v%i==0){
                int l=v/i;
                for(int j=1;j<=l;j++){
                    if(l%j==0){
                        int k=l/j;
                        ans=min(ans,2LL*(i*j+k*j+k*i));
                    }
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    E .Entirely Unsorted Sequences

    https://blog.csdn.net/ccsu_cat/article/details/86754931

    G .Game Night

    模拟几种排列即可

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    int sum[maxn][3],N; char c[maxn];
    int get(int A,int B,int C)
    {
        int res=0;
        rep(i,1,N){
            int X=sum[i+sum[N][A]-1][A]-sum[i-1][A];
            int Y=sum[i+sum[N][A]+sum[N][B]-1][B]-sum[i+sum[N][A]-1][B];
            int Z=sum[i+N-1][C]-sum[i+sum[N][A]+sum[N][B]-1][C];
            res=max(res,X+Y+Z);
            //cout<<A<<" "<<B<<" "<<C<<" : "<<i<<" "<<res<<endl;
        }
        return N-res;
    }
    int main()
    {
        scanf("%d%s",&N,c+1);
        int ans=N;
        rep(i,1,N) c[N+i]=c[i];
        rep(i,1,N+N){
            rep(j,0,2) sum[i][j]=sum[i-1][j];
            if(c[i]=='A') sum[i][0]++;
            if(c[i]=='B') sum[i][1]++;
            if(c[i]=='C') sum[i][2]++;
        }
        rep(i,0,2)
         rep(j,0,2)
          rep(k,0,2)
           if(i!=j&&i!=k&&j!=k)
            ans=min(ans,get(i,j,k));
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    I. In Case of an Invasion, Please...

    题意:给定N城市每个城市人数是Pi,M双向路,其中S个点(S<=10)是避难所,避难所容量是Ci,(N<1e5; Ci,Pi<1e9)最小化最大的转移时间,使得所有人都转移到避难所。

    思路:二分+最大流。由于图比较大,此题需要一些优化才能过。

    由于上限是1e14; 所以二分次数是50次; 我们可以把距离离散化上线变为了1e6,二分次数是20;这是一个优化。

    第二个优化,对于二分到的mid,如果一个城市可以去的避难所容量之和<P[i],那么显然不用跑网络流也知道不合法。

    还有就是sap跑二分图比较慢,要用dinic。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e5+150;
    ll inf=1ll<<60;
    struct Edge
    {
        int from,to;
        ll cap,flow;
    };
    struct Dinic
    {
        int n,m,s,t;
        vector<Edge>edges;
        vector<int>G[maxn];
        bool vis[maxn];
        int d[maxn],cur[maxn];
        void init(int n)
        {
            this->n=n;
            for(int i=0;i<n;i++)
            G[i].clear();
            edges.clear();
        }
        void AddEdge(int from,int to,ll cap)
        {
            edges.push_back((Edge){from,to,cap,0});
            edges.push_back((Edge){to,from,0,0});
            m=edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
        bool bfs()
        {
            memset(vis,0,sizeof(vis));
            queue<int>Q;
            Q.push(s);
            d[s]=0;
            vis[s]=1;
            while(!Q.empty())
            {
                int x=Q.front();Q.pop();
                for(int i=0;i<G[x].size();i++)
                {
                    Edge& e=edges[G[x][i]];
                    if(!vis[e.to]&&e.cap>e.flow)
                    {
                        vis[e.to]=1;
                        d[e.to]=d[x]+1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        ll dfs(int x,ll a)
        {
            if(x==t||a==0)return a;
            ll flow=0,f;
            for(int& i=cur[x];i<G[x].size();i++)
            {
                Edge& e=edges[G[x][i]];
                if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
                {
                    e.flow+=f;
                    edges[G[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0)break;
                }
            }
            return flow;
        }
        ll Maxflow(int s,int t)
        {
            this->s=s,this->t=t;
            ll flow=0;
            while(bfs())
            {
                memset(cur,0,sizeof(cur));
                flow+=dfs(s,inf);
            }
            return flow;
        }
    }solve;
    ll d[15][maxn],sum,vis[maxn];
    vector<int>G[maxn],dis[maxn];
    struct node
    {
        int u;
        ll w;
        node(int a,ll b)
        {
            u=a,w=b;
        }
        bool operator<(const node&t)const
        {
            return w>t.w;
        }
    };
    priority_queue<node>q;
    void dij(int k,int s,int n)
    {
        for(int i=1;i<=n;i++)d[k][i]=inf,vis[i]=0;
        d[k][s]=0;
        q.push(node(s,0));
        while(!q.empty())
        {
            node e=q.top();q.pop();
            int u=e.u; vis[u]=0;
            for(int i=0;i<G[u].size();i++)
            {
                int v=G[u][i];
                if(d[k][v]>d[k][u]+dis[u][i])
                {
                    d[k][v]=d[k][u]+dis[u][i];
                    if(!vis[v]) vis[v]=1,q.push(node(v,d[k][v]));
                }
            }
        }
    }
    int p[maxn],s[maxn],c[maxn],tot; ll B[maxn*20],fcy[maxn];
    int main()
    {
        int n,m,k,u,v,w;
        scanf("%d%d%d",&n,&m,&k);
        int S=0,T=n+k+1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&p[i]);
            sum+=p[i];
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(v);
            dis[u].push_back(w);
            G[v].push_back(u);
            dis[v].push_back(w);
        }
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d",&s[i],&c[i]);
            dij(i,s[i],n);
        }
        for(int i=1;i<=k;i++)
         for(int j=1;j<=n;j++) B[++tot]=d[i][j];
        sort(B+1,B+tot+1);
        tot=unique(B+1,B+tot+1)-(B+1);
        ll l=1,r=tot,mid,ans;
        while(l<=r)
        {
            mid=(l+r)/2;
            solve.init(T+1);
            for(int i=1;i<=n;i++) fcy[i]=0;
            for(int i=1;i<=n;i++)
            for(int j=1;j<=k;j++)
            if(d[j][i]<=B[mid])
            solve.AddEdge(i,n+j,inf),fcy[i]+=c[j];
            bool F=true;
            for(int i=1;i<=n;i++)
            if(fcy[i]<p[i]){ F=false; break;}
            if(!F) {l=mid+1;continue;}
            for(int i=1;i<=n;i++)
            solve.AddEdge(S,i,p[i]);
            for(int i=1;i<=k;i++)
            solve.AddEdge(n+i,T,c[i]);
            ll res=solve.Maxflow(S,T);
            if(res==sum) r=mid-1,ans=B[mid];
            else l=mid+1;
        }
        printf("%lld
    ",ans);
    }
    View Code

    J .Janitor Troubles

    题意:给定ABCD四条边,让你组成一个面积最大的四边形,保证有解。

    思路:比赛时三分做的,1A。但是赛后拿去做hduwa掉了,还是没弄清楚。

    三分:枚举相邻边的组合形式,然后对对角线进行三分。 结论是当三分到对角线的对面两个角都是直角时,答案最大,此时正好有外接圆。

    定理:根据上面结论,相当于四边形是圆内接四边形,我们可以至直接用海伦公式的变形;

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    double X[5],ans;
    double S(double x,double y,double x1,double y1,double z)
    {
        double p=(x+y+z)/2,p1=(x1+y1+z)/2;
        return sqrt(p*(p-x)*(p-y)*(p-z))+sqrt(p1*(p1-x1)*(p1-y1)*(p1-z));;
    }
    double get(int i,int j,int k,int p)
    {
        double Mn=max(X[j]-X[i],X[p]-X[k]),Mx=min(X[j]+X[i],X[p]+X[k]);
        if(Mn>Mx) return 0.0;
        int T=100; double L=Mn,R=Mx,res=0.0;
        while(T--){
            double Mid1=L+(R-L)/3,Mid2=R-(R-L)/3;
            double F1=S(X[i],X[j],X[k],X[p],Mid1);
            double F2=S(X[i],X[j],X[k],X[p],Mid2);
            if(F1>=F2) res=max(F1,res),R=Mid2;
            else res=max(F2,res),L=Mid1;
        }
        return res;
    }
    int main()
    {
        rep(i,1,4) scanf("%lf",&X[i]);
        sort(X+1,X+4+1);
        rep(i,1,4)
         rep(j,i+1,4)
          rep(k,1,4)
           rep(p,k+1,4)
            if(i!=k&&i!=p&&j!=k&&j!=p){
             ans=max(ans,get(i,j,k,p));
        }
        printf("%.10lf
    ",ans);
        return 0;
    }
    View Code
    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    double X[5],ans;
    double get()
    {
        double res=0.0,p=(X[1]+X[2]+X[3]+X[4])/2;
        res=sqrt((p-X[1])*(p-X[2])*(p-X[3])*(p-X[4]));
        return res;
    }
    int main()
    {
        rep(i,1,4) scanf("%lf",&X[i]);
        ans=get();
        printf("%.10lf
    ",ans);
        return 0;
    }
    View Code

    K .Kingpin Escape

    题意:给定一棵有根树,现在让你加最少的边,使得无论原图上哪条边被砍掉,从任意点出发都可以回到根节点。

    思路:首先把保证至少两个点与根相邻,所以如果根只有一条边与它相邻,它需要加边。 其次,所有叶子节点需要加边,因为他和父亲被砍断后就GG了。

     我们按照一定顺序把这些点连边即可。 假设X个点需要连边,那么最少需要加(X+1)/2条边。然后两两连边即可,但是注意至少一条新加的边连通了根的两个子树。

    所以我们按照DFS序,然后q[i]+q[X/2+i]连边,这样可以保证,并不是所有新加的边都在同一个子树(这样可能合法,因为砍掉根与儿子后,子树无法到达根)里。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2000010;
    int Laxt[maxn],Next[maxn],To[maxn];
    int sz[maxn],cnt,q[maxn],tot;
    void add(int u,int v){
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
    }
    void dfs(int u,int f)
    {
        if(sz[u]==1) q[++tot]=u-1;
        for(int i=Laxt[u];i;i=Next[i])
         if(To[i]!=f) dfs(To[i],u);
    }
    int main()
    {
        int N,M,u,v;
        scanf("%d%d",&N,&M); M++;
        rep(i,1,N-1){
            scanf("%d%d",&u,&v);
            u++; v++; sz[u]++; sz[v]++;
            add(u,v); add(v,u);
        }
        dfs(M,0);
        int ans=(tot+1)/2;
        printf("%d
    ",ans);
        rep(i,1,tot/2) printf("%d %d
    ",q[i],q[i+tot/2]);
        if(tot&1) printf("%d %d
    ",q[1],q[tot]);
        return 0;
    }
    View Code
  • 相关阅读:
    Android的消息机制
    AndroidVolley框架的使用
    Android事件分发机制浅谈(三)源码分析(View篇)
    Java 编程下简介 Class 与类加载
    [ZJOI2007]最大半连通子图
    [HNOI2012]永无乡
    [HEOI2016/TJOI2016]排序
    CSS 条件缩放图片
    CSS图片垂直居中
    最近写 ASP.NET 中出现的错误 & 实现DataTable和DataSet类型的客户端/服务器端自动转换
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10353767.html
Copyright © 2011-2022 走看看