zoukankan      html  css  js  c++  java
  • 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

    题目传送门

    题号 A B C D E F G H I J K L
    状态  .  . Ο Ο Ø Ο Ο Ο

    Ο:当场

    Ø:已补

    .  :  待补

    A Drawing Borders

    待补。

    B Buildings

    待补。

    C Joyride

    Code:kk

    Thinking:kk

      题意游乐场有n个设施,有m条人行道,游乐设施会花费ti的时间和pi的钱,人行道需要花费t的时间,你需要用最少的钱恰好游玩x的时间,起点是1,终点是1,求最少的钱是多少4,并且1必须经过两次。

      这道题做的我心情复杂。。

      先说解法吧,其实很简单,$dp[i][t]$表示到第i个节点,已经使用了t的时间的最小花费,那么状态转移方程就是$dp[v][t]=min(do[u][t-tv]$,然后用队列存放状态,跑一个类似dijkstra堆优化的东西,只不过不用优先队列,特别注意1必须经过两次,所以一开始要判断一下一号节点的时间。

      是不是很简单呢。。然而为了写的方便,我把每个节点自己和自己都连了一个环,然后这样的边数就变成了3*n,而我链式前向星的结构体只开了两倍,显示wa9,连带着队友一起自闭了,其他好多题可以做的啊啊啊啊啊

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=2010;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    ll dp[maxn][maxn],p[maxn],maxx;
    bool vis[maxn][maxn];
    int n,m,x,t,head[maxn],tot;
    int tim[maxn];
    struct node{
        int u,t;
    }st;
    struct edge{
        int to,Next;
        ll w;
    }a[maxn<<1];
    inline void addv(int u,int v,int w){
        a[++tot].to=v;
        a[tot].w=w;
        a[tot].Next=head[u];
        head[u]=tot;
    }
    void bfs(){
        clr(dp,inf);
        if(tim[1]>=x)return;
        dp[1][tim[1]]=p[1];
        queue<node>q;
        q.push({1,tim[1]});
    //    vis[1][tim[1]]=1;
        
        while(!q.empty())
        {
            st=q.front();
            q.pop();
            int u=st.u,ti=st.t;
        //    vis[u][ti]=0;
            if(st.t>x)continue;
            for(int i=head[u];i!=-1;i=a[i].Next)
            {
                int v=a[i].to;
                int cotime=a[i].w;
                if(cotime+ti+tim[v]>x)continue;
            //    printf("dbbug
    ");
                if(dp[v][cotime+ti+tim[v]]>dp[u][ti]+p[v]){
                
                    dp[v][cotime+ti+tim[v]]=dp[u][ti]+p[v];
                //    printf("%d  %d   %d
    ",u,v,dp[v][cotime+ti+tim[v]]);
                //    if(!vis[v][cotime+ti+tim[v]]){
                        q.push({v,cotime+ti+tim[v]});
                    //    vis[v][cotime+ti+tim[v]] = 1;
                //    }
                }
            }
        }
        maxx=min(maxx,dp[1][x]);
    }
    void pop()
    {
    
                for(int i=1;i<=101001;i++) 
                 for(int j=1;j<=101010;j++)
                     ;
    }
    int main(){
        while(cin>>x)
        {
        
            clr(head,-1),tot=0;
            scanf("%d%d%d",&n,&m,&t);
        
            for(int i=1;i<=m;i++)
            {
                int u,v,w;
                scanf("%d%d",&u,&v);
                if(u==v) pop();
                addv(u,v,t);
                addv(v,u,t);
            }
            for(int i=1;i<=n;i++)
            {
                scanf("%d%lld",&tim[i],&p[i]);
                addv(i,i,0);
            }
            
            maxx=inf;
            bfs();
            if(maxx==inf)puts("It is a trap.");
            else printf("%lld
    ",maxx);
        }
    }
    View Code

    D.Pants On Fire

    Thinking:zz

    Code:zz

    题意:先给n个谁比谁菜的关系,然后给m个谁比谁菜的关系,判断这m个关系是正确的、错误的还是不明确的。

    题解:按n个关系建图,然后直接bfs暴力判断这m个关系是不是对的。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=110010;
    char c[1010],d[1010],tmp[1010];
    unordered_map<string,int>mp;
    vector<int>ve[1010];
    int v[550];
    int main()
    {
        int n,m,i,j,k,cnt,xx,yy,pos,si,qq,ans;
        while(~scanf("%d %d",&n,&m))
        {
            for(i = 0;i <= 1000;i++)
            {
                ve[i].clear();
            }
            cnt = 1;
            for(i = 0;i < n;i++)
            {
                scanf("%s",c);
                scanf("%s",tmp);
                scanf("%s",tmp);
                scanf("%s",tmp);
                scanf("%s",d);
                if(!mp[c])
                {
                    mp[c] = cnt++;
                }
                if(!mp[d])
                {
                    mp[d] = cnt++;
                }
                xx = mp[c];
                yy = mp[d];
                ve[yy].push_back(xx);
            }
            for(i = 0;i < m;i++)
            {
                scanf("%s",c);
                scanf("%s",tmp);
                scanf("%s",tmp);
                scanf("%s",tmp);
                scanf("%s",d);
                xx = mp[c];
                yy = mp[d];
                if(xx == 0 || yy == 0)
                {
                    printf("Pants on Fire
    ");
                    continue;
                }
                else
                {
                    queue<int>q;
                    q.push(yy);
                    memset(v,0,sizeof(v));
                    v[yy] = 1;
                    qq = 0;
                    //printf("111
    ");
                    while(!q.empty())
                    {
                        //printf("222
    ");
                        pos = q.front();
                        q.pop();
                        //printf("2222  %d
    ",pos);
                        si = ve[pos].size();
                        //printf("22222
    ");
                        for(j = 0;j < si;j++)
                        {
                            //printf("333
    ");
                            if(!v[ve[pos][j]])
                            {
                                v[ve[pos][j]] = 1;
                                if(xx == ve[pos][j])
                                {
                                    qq = 1;
                                    break;
                                }
                                //printf("  %d
    ",ve[pos][j]);
                                q.push(ve[pos][j]);
                            }
                        }
                        if(qq)
                        {
                            break;
                        }
                    }
                    //printf("999
    ");
                    if(qq)
                    {
                        ans = 1;
                    }
                    else
                    {
                        //printf("111
    ");
                        queue<int>qqq;
                        qqq.push(xx);
                        memset(v,0,sizeof(v));
                        v[xx] = 1;
                        qq = 0;
                        while(!qqq.empty())
                        {
                            pos = qqq.front();
                            qqq.pop();
                            si = ve[pos].size();
                            for(j = 0;j < si;j++)
                            {
                                if(!v[ve[pos][j]])
                                {
                                    v[ve[pos][j]] = 1;
                                    if(yy == ve[pos][j])
                                    {
                                        //printf("5555
    ");
                                        qq = 1;
                                        break;
                                    }
                                    qqq.push(ve[pos][j]);
                                }
                            }
                            if(qq)
                            {
                                break;
                            }
                        }
                        if(qq)
                        {
                            ans = 2;
                        }
                        else
                        {
                            ans = 3;
                        }
                    }
                }
                if(ans == 1)
                {
                    printf("Fact
    ");
                }
                else if(ans == 2)
                {
                    printf("Alternative Fact
    ");
                }
                else
                {
                    printf("Pants on Fire
    ");
                }
            }
        }
    }
    View Code

    E Perpetuum Mobile

    待补

    F Plug It In!

    补题:kk

      这题看上去就很模板的样子。。比赛的时候没做真是太蠢了。。

      暴力枚举每个点,然后每次都重新跑二分图显然是会超时的,但是我们发现,如果新增加两个节点,就可以直接在原图的增广路径上来跑二分图,这样只需要对新增加的两个点跑就可以了,所以就把原图复制一下,(只需要复制girl数组就好)然后暴力枚举每个点。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1510;
    vector<int >ve[maxn];
    int girl[maxn],vis[maxn],match[maxn];
    int n,m,k;
    bool dfs(int x)
    {
        for(auto v:ve[x])
        {
            if(vis[v])continue;
            vis[v]=1;
            if(girl[v]==0||dfs(girl[v])){
                girl[v]=x;
                return true;
            }
        }
        return false;
    }
    bool dfs_2(int x)
    {
        for(auto v:ve[x])
        {
            if(vis[v])continue;
            vis[v]=1;
            if(match[v]==0||dfs_2(match[v])){
                match[v]=x;
                return true;
            }
        }
        return false;
    }
    int main(){
        while(cin>>m>>n>>k)
        {
            for(int i=1;i<=k;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                ve[u].push_back(v);
            }
            int ans=0;
            for(int i=1;i<=m;i++)
            {
                clr(vis,0);
                if(dfs(i))ans++;
            }
            int maxx=ans;
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    match[j]=girl[j];
                }
                ve[1+m].clear(),ve[2+m].clear();
                for(int j=0;j<ve[i].size();j++)
                {
                    
                    ve[1+m].push_back(ve[i][j]);
                    ve[2+m].push_back(ve[i][j]);
                }
                int tep=ans;
                for(int j=m+1;j<=m+2;j++)
                {
                    clr(vis,0);
                    if(dfs_2(j))tep++;
                }
                maxx=max(maxx,tep);
            }
            cout<<maxx<<endl;
        }
    }
    View Code

    G Water Testing

    皮克定理

    皮克定理:指一个计算点阵中顶点在格点上的多边形面积公式,该公式可以表示为$2S=2a+b-2$,其中a表示多边形内部的点数,b表示多边形边界上的点数,S表示多边形的面积。

    Code:zz

    Thinking:zz

    题意:按顺序给定一个凸包上的所有点,判断凸包内有多少个整数点(凸包上的点不算)。

    题解:设凸包上的点数为a,凸包内的点数为b,凸包的面积为s,则s=b+a/2-1(皮克定理),这样一来算出s(用叉乘算)和a(用gcd算)就行了。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1010;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    struct ss
    {
        long long a,b;
    }z[100010],zz;
    inline long long Gcd(long long n,long long m)
    {
        long long r;
        while(n % m != 0)
        {
            r = n % m;
            n = m;
            m = r;
        }
        return m;
    }
    int main(){
        int n,i,j;
        long long s,a,xx,yy,tmp,ans;
        while(~scanf("%d",&n))
        {
            for(i = 1;i <= n;i++)
            {
                scanf("%lld %lld",&z[i].a,&z[i].b);
            }
            z[n + 1] = z[1];
            s = 0;
            for(i = 1;i <= n;i++)
            {
                s += z[i].a * z[i + 1].b - z[i].b * z[i + 1].a;
            }
            //printf("  s = %lld
    ",s);
            if(s <= 0)
            {
                for(i = 1;i <= n / 2;i++)
                {
                    zz = z[i];
                    z[i] = z[n - i + 1];
                    z[n - i + 1] = zz;
                }
                z[n + 1] = z[1];
                s = 0;
                for(i = 1;i <= n;i++)
                {
                    s += z[i].a * z[i + 1].b - z[i].b * z[i + 1].a;
                }
            }
            a = 0;
            for(i = 1;i <= n;i++)
            {
                xx = z[i].a - z[i + 1].a;
                yy = z[i].b - z[i + 1].b;
                if(xx < 0)
                {
                    xx = -xx;
                }
                if(yy < 0)
                {
                    yy = -yy;
                }
                if(xx == 0 || yy == 0)
                {
                    xx = max(xx,yy);
                    a += xx;
                }
                else
                {
                    tmp = Gcd(xx,yy);
                    a += tmp;
                }
            }
            ans = s + 2 - a;
            printf("%lld
    ",ans / 2);
        }
    }
    View Code

    H Ratatöskr

    待补

    I Überwatch

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=110010;
    int n,m,x[301000],g[301000],dp[301000];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&x[i]);
        for(int i=m+1;i<=n;i++)
        {
            dp[i]=max(dp[i-1],g[i-m]+x[i]);
            g[i]=max(g[i-1],dp[i]);
        }
        printf("%d
    ",g[n]);
    }
    View Code

    J Word Clock

    K You Are Fired!

    Code:zz

    Thinking:zz

    题意:解雇最少的员工,使得至少节省d元,但最多解雇k个员工。

    题解:按工资从大到小排序,优先解雇工资高的。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=110010;
    struct s
    {
        char c[20];
        long long v;
    }z[10010];
    inline bool comp(s a,s b)
    {
        return a.v > b.v;
    }
    int main(void)
    {
        int n,k,i;
        long long d,zz;
        while(~scanf("%d %lld %d",&n,&d,&k))
        {
            for(i = 0;i < n;i++)
            {
                scanf("%s %lld",z[i].c,&z[i].v);
            }
            sort(z,z + n,comp);
            zz = 0;
            int j;
            for(i = 0;i < k;i++)
            {
                zz += z[i].v;
                if(zz >= d)
                {
                    break;
                }
            }
            if(zz >= d)
            {
                printf("%d
    ",i + 1);
                for(j = 0;j <= i;j++)
                {
                    printf("%s, YOU ARE FIRED!
    ",z[j].c);
                }
            }
            else
            {
                printf("impossible
    ");
            }
        }
    }
    View Code

    赛后总结:

      kk:今天被C题搞死了,想出ac想法的时候只有一点点人ac这道题,真正ac的时候却已经是四个小时后了,而且是一个小bug。不但自己没做其他题,还拖累了队友的做题速度,其实还有其他很多可做的题目,一定要多看题!以后遇到这样的情况,要勇于换人重写代码。

      zz:今天就做了三道水题,读了题面就知道怎么做了,后来和队友一起搞C,其它题基本没怎么想。

  • 相关阅读:
    c# 读改xml
    window
    c# 日期字符格式化
    验证字符串是否为数字
    MySQL常用操作基本操作
    将参数扩展为指定长度的字符串,不足位数的在前方加0
    hp服务器重装后,启动apache和tomcat和mysql
    [转] 各种取整数函数(VB)
    [原] access97中textbox类似vb的maxlength功能的实现
    [转] csv文件的读写
  • 原文地址:https://www.cnblogs.com/mountaink/p/10486580.html
Copyright © 2011-2022 走看看