2014 Benelux Algorithm Programming Contest (BAPC 14)

来源:互联网 发布:淘宝一件代发是真的吗 编辑:程序博客网 时间:2024/06/05 02:31

2014 Benelux Algorithm Programming Contest (BAPC 14)

算5题?嘻嘻

Gym - 101512B Button Bashing

水题

#include<bits/stdc++.h>using namespace std;const int maxn=7206;const int inf=0x3f3f3f3f; int t[maxn],d[2*maxn];int main(){    int n,m,T;    cin>>T;    while(T--){        scanf("%d %d",&n,&m);        for(int i=1;i<=n;i++)            scanf("%d",t+i);        queue<int>q;        pair<int,int> ans=make_pair(inf,inf);        memset(d,0x3f,sizeof d);        d[0]=0,q.push(0);        while(!q.empty()){            int nd=q.front();            q.pop();            if(nd>=m)ans=min(ans,make_pair(nd,d[nd]));            for(int i=1;i<=n;i++){                int u=nd+t[i];                if(u<0)u=0;                if(u>3600)u=3600;                if(d[u]==inf)                    d[u]=d[nd]+1,q.push(u);            }        }        cout<<ans.second<<" "<<ans.first-m<<endl;    }    return 0;}

Gym - 101512E Excellent Engineers

知道树状数组的我哭了起来。
按A维排序,在B处插入C的值,维护区间最小值。查询时看(1~B)的最小值,有比C小的就加一。

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN=2e5+5;int n, maxVal;struct Operation{    int a, b, c, w;    int f;//ans    bool operator <(const Operation &r)const    {        //return a<r.a || (a==r.a&&b<r.b) || (a==r.a&&b==r.b&&c<r.c);        return (a==r.a&&b==r.b) ? c<r.c : (a==r.a ? b<r.b : a<r.a);    }}a[MAXN], t[MAXN];LL c[MAXN];inline int lowbit(int x) { return x&-x; }inline void add(int p, int v) { for(;p<=maxVal;p+=lowbit(p)) c[p]+=v; }inline LL sum(int p){    LL re=0;    for(;p;p-=lowbit(p)) re+=c[p];    return re;}int ans[MAXN];LL rres;void CDQ(int l, int r){    if(l==r) return;    int mid=(l+r)>>1;    CDQ(l, mid);CDQ(mid+1, r);    int i=l, j=mid+1, p=l;    while(i<=mid||j<=r)    {        if(j>r||(i<=mid&&a[i].b<=a[j].b)) add(a[i].c, a[i].w), t[p++]=a[i++];        else a[j].w+=sum(a[j].c), t[p++]=a[j++];    }    for(int i=l;i<=mid;i++) add(a[i].c, -a[i].w);    for(int i=l;i<=r;i++) a[i]=t[i];}int main(){    int T;scanf("%d",&T);    while(T--)    {        scanf("%d", &n);        for(int i=1;i<=n;i++)            scanf("%d",&a[i].a),scanf("%d",&a[i].b),scanf("%d",&a[i].c),a[i].w=1;        sort(a+1, a+1+n);        int p=1;        maxVal=MAXN-1;        rres=0;        CDQ(1, n);        for(int i=1;i<=n;i++)            if(a[i].w==1) rres++;        printf("%d\n",rres);    }    //system("pause");}

Gym - 101512I Interesting Integers

数学题,at老谭

#include<bits/stdc++.h>using namespace std;typedef long long LL;LL f[49];LL e_gcd(LL a,LL b,LL &x,LL &y)  {      if(b==0)      {          x=1;          y=0;          return a;      }      LL ans=e_gcd(b,a%b,x,y);      LL temp=x;      x=y;      y=temp-a/b*y;      return ans;  }  int main(){    f[1]=1,f[2]=1;    for(int i=3;i<=47;i++)        f[i]=f[i-1]+f[i-2];    int T;    LL  n;    cin>>T;    while(T--){        cin>>n;        LL ansx,ansy;        ansx=n/2;        ansy=n-ansx;        for(int i=3;;i++){            if(f[i]>n)break;            LL x=-1,y=-1;            LL g=e_gcd(f[i-2],f[i-1],x,y);            if(n%g)continue;            x*=(n/g),y*=(n/g);            LL t=(y-x)/(f[i-2]+f[i-1]);            x=x+t*f[i-1];            y=y-t*f[i-2];            if(x>y){                x-=f[i-1];                y+=f[i-2];            }            if(x<=0 || y<=0)continue;            if(ansy>y){                ansy=y,ansx=x;            }            else if(ansy==y && ansx>x)                ansy=y,ansx=x;        }        printf("%I64d %I64d\n",ansx,ansy);    }    return 0;}

这时我冲上去写了一发暴力的K,果然gg。。

Gym - 101512G Growling Gears

大水题,连精度都不卡,不知道为什么过的人巨少,可能这种训练赛大家都不削于做水题。。
就是给你一堆抛物线y=ax2+bx+c,求最高点。直接顶点公式4acb24a

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN=2e5+5;int main(){    int T;scanf("%d",&T);    while(T--)    {        int n;scanf("%d",&n);        double ma;int mai=1;        for(int i=1;i<=n;i++)        {            LL a,b,c;scanf("%I64d %I64d %I64d",&a,&b,&c);            double fz=-4*a*c-b*b;            double fm=-4*a;            if(i==1) ma=fz/fm;            else            {                if(ma<fz/fm)                {                    ma=fz/fm;                    mai=i;                }            }        }        printf("%d\n",mai);    }    //system("pause");    return 0;}

在比赛临结束搞过了A。。

Gym - 101512A Avoiding the Apocalypse

网络流。。根lrj那个运送宇宙超级计算机一模一样。。按时间拆点,注意细节就好。
超级源向s的0时刻连容量g的边,表示0时刻初始人数是g。
每个点的时刻t要向t+1连边,容量无穷,表示可以原地不动。
然后每个医院的任何时刻都要向超级汇连边,表示一旦到医院就算流。
在按时间连其他边。

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN=2e5+5;const int oo=0x3f3f3f3f;struct Dinic{    struct Edge{        int from, to, cap, flow;//cap容量 flow流量        Edge(){}        Edge(int u, int v, int c, int f){ from=u;to=v;cap=c;flow=f; }    };    vector<Edge> edges;//顺序的插入边    vector<int> G[MAXN];//保存边号    bool vis[MAXN];//BFS使用    int d[MAXN];    int cur[MAXN];    void init(int n)    {        for(int i=0;i<=n;i++) G[i].clear();        edges.clear();    }    void AddEdge(int from, int to, int cap)    {        edges.push_back(Edge(from, to, cap, 0));        edges.push_back(Edge(to, from, 0, 0));//单向边第三个参数写0,双向边写cap        int t_m=edges.size();        G[from].push_back(t_m-2);        G[to].push_back(t_m-1);    }    bool BFS(int s, int t)    {        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];    }    int DFS(int x, int a, int s, int t)    {        if(x==t||a==0) return a;        int 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), s, t))>0)            {                e.flow+=_f;                edges[G[x][i]^1].flow-=_f;                flow+=_f;                a-=_f;                if(a==0) break;            }        }        return flow;    }    int Maxflow(int s, int t)    {        int flow=0;        while(BFS(s, t))        {            memset(cur, 0, sizeof(cur));            flow+=DFS(s, oo, s, t);        }        return flow;    }}dinic;int main(){    int T;scanf("%d",&T);    while(T--)    {        int n;scanf("%d",&n);        int s,g,k;scanf("%d%d%d",&s,&g,&k);        dinic.init(n*(k+1)+5);        int m;scanf("%d",&m);        int super_s=(k+1)*n+1;        int super_t=(k+1)*n+2;        dinic.AddEdge(super_s,s,g);        while(m--)        {            int tmp;            scanf("%d",&tmp);            for(int i=0;i<=k;i++)                dinic.AddEdge(tmp+n*i,super_t,g);        }        for(int i=1;i<=n;i++)            for(int j=0;j<k;j++)            {                dinic.AddEdge(i+n*j,i+n*(j+1),g);            }        int r;scanf("%d",&r);        for(int i=1;i<=r;i++)        {            int a,b,p,t;scanf("%d%d%d%d",&a,&b,&p,&t);            int tm=0;            while(tm+t<=k)            {                dinic.AddEdge(a+n*(tm),b+n*(tm+t),p);                tm++;            }        }        int res=dinic.Maxflow(super_s,super_t);        printf("%d\n",min(res,g));    }    //system("pause");    return 0;}

开始赛后补题。。说实话感觉D也不难,要是我当时不写K的暴力或许就能出了。。

Gym - 101512D Dropping Directions

这题很蛇皮,样例巨难画。不过耐着心画下来,实际每个点度都是4。我们假设一个路标都不设置,从目标点开始搜索,那么会搜出两个欧拉回路。因为目标点度是4,一个入一个出,所以会有两个回路。模拟样例2和样例3(因为他俩图一样,省事),发现剩下的欧拉回路一个回路添一个路标就可以了,因为一个路标就可以让这条回路全指向通往目标点的回路。

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAXN=100007;const int oo=0x3f3f3f3f;int vis[MAXN][4];int to[MAXN][4];int go(int p,int f){    if(to[p][0]==f) {vis[p][0]=1,vis[p][2]=1;return to[p][2];}    if(to[p][1]==f) {vis[p][1]=1,vis[p][3]=1;return to[p][3];}    if(to[p][2]==f) {vis[p][2]=1,vis[p][0]=1;return to[p][0];}    if(to[p][3]==f) {vis[p][3]=1,vis[p][1]=1;return to[p][1];}    assert("No Way!");}queue<pair<int,int>> que;void sousuo(int u,int i){    if(!vis[u][i])        {            int now=to[u][i],la=u;vis[u][i]=1;            while(1)            {                int v=go(now,la);                la=now,now=v;                if(now==u)                {                    for(int j=0;j<4;j++)                        if(to[u][j]==la) vis[u][j]=1;                    break;                }            }        }}int main(){    int T;scanf("%d",&T);    while(T--)    {        memset(vis,0,sizeof(vis));        int n,s;scanf("%d%d",&n,&s);        for(int i=1;i<=n;i++)        {            scanf("%d%d%d%d",&to[i][0],&to[i][1],&to[i][2],&to[i][3]);        }        for(int i=0;i<4;i++)            if(!vis[s][i])                sousuo(s,i);//        for(int i=1;i<=n;i++)//        {//            printf("%d  ",i);//            for(int j=0;j<4;j++)//            {//                printf("%d:%d ",to[i][j],vis[i][j]);//            }//            printf("\n");//        }        int cnt=0;        for(int i=1;i<=n;i++)        {            for(int j=0;j<4;j++)            {                if(!vis[i][j])                    sousuo(i,j),cnt++;            }        }        printf("%d\n",cnt);    }    //system("pause");    return 0;}

Gym - 101512C Citadel Construction

凸包的最大内接四边形,旋转卡壳法。代码太长了,不贴了。

Gym - 101512K Key to Knowledge

正解是折半搜索。用空间换时间,将前一半215的结果存到map里面,搜索后一半时去里面查找。

#include<bits/stdc++.h>using namespace std;string ans[15];int grade[15];map<string, pair<int, long long>> rec;int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int t;    cin>>t;    while(t--)    {        int n, m;        cin>>n>>m;        rec.clear();        for(int i=1;i<=n;i++)        {            cin>>ans[i]>>grade[i];        }        int mid=m/2;        for(long long a=0;a<(1ll<<mid);a++)        {            string status="";            for(int i=1;i<=n;i++)            {                int p=0;                long long aa=a;                for(int j=0;j<mid;j++)                {                    if((aa&1)==ans[i][j]-'0') p++;                    aa>>=1;                }                int relase=grade[i]-p;                if(relase<0) break;                status+='0'+relase;            }            if(status.size()==n)            {                rec[status].first++;                rec[status].second=a;            }        }        long long solution=0;        long long left, right;        for(long long a=0;a<(1ll<<(m-mid));a++)        {            string status="";            for(int i=1;i<=n;i++)            {                int p=0;                long long aa=a;                for(int j=mid;j<m;j++)                {                    int nb=ans[i][j]-'0';                    if((aa&1)==nb) p++;                    aa>>=1;                }                int relase=grade[i]-p;                if(relase<0) break;                status+='0'+p;            }            if(status.size()==n)            {                auto it=rec.find(status);                if(it!=rec.end())                {                    solution+=it->second.first;                    left=it->second.second;                    right=a;                }            }        }        if(solution==1)        {            string ans="";            for(int i=0;i<mid;i++)            {                ans+='0'+(left&1);                left>>=1;            }            for(int i=mid;i<m;i++)            {                ans+='0'+(right&1);                right>>=1;            }            cout<<ans<<'\n';        }        else        {            cout<<solution<<" solutions\n";        }    }    return 0;}

剩下的,J是个水题模拟,剩下两个没看,好像题解都没有。。。

阅读全文
0 0