• 2016 China Collegiate Programming Contest Final


    2016 China Collegiate Programming Contest Final

    Table of Contents 2016 China Collegiate Programming Contest FinalProblem A:Problem J:Problem H:

    Problem A:

    题意:喝咖啡,每三杯就又可以有免费一杯,求最少花费;

    分析:贪心;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 100000+5;
    int a[maxn];
    
    int main()
    {
        int t;
        scanf("%d",&t);
        int kase = 0;
        while(t--) {
            int n;
            scanf("%d",&n);
            int sum = 0;
            for(int i=0;i<n;i++) {
                scanf("%d",&a[i]);
                sum +=a[i];
            }
            sort(a,a+n);
    
            for(int i=n-3;i>=0;i-=3)
                sum-=a[i];
    
            printf("Case #%d: %d
    ",++kase,sum);
    
        }
        return 0;
    }
    

    Problem J:

    题意:题意很长,CCPC比赛规则,给出一个队伍,看他是否能进WF,CCPC分两个部分,X 是从五大赛区中选X个,Y是在EC比赛中选Y个,X+Y = G,G是确定的,然后调整X,Y使得给出的这个队伍恰好不能进WF时的最小Y,要是无论怎么调整XY,都能进WF,输出ADVANCED!

    分析:g<=20 记录两种规则中的这个队伍的排名k,kk,枚举x,y即可;

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    string a1[25],a2[25],a3[25],a4[25],a5[25];
    string ec[25];
    
    int main()
    {
    
        //freopen("in.txt","r",stdin);
        int kase = 1;
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int g;
            scanf("%d",&g);
            string ans;
            cin>>ans;
    
            for(int i=0; i<20; i++)
                cin>>a1[i];
    
            for(int i=0; i<20; i++)
                cin>>a2[i];
    
            for(int i=0; i<20; i++)
                cin>>a3[i];
    
            for(int i=0; i<20; i++)
                cin>>a4[i];
    
            for(int i=0;i<20;i++)
                cin>>a5[i];
    
            for(int i=0; i<20; i++)
                cin>>ec[i];
    
            int k = 1;
            set<string> s;
            bool flag = false;
            for(int i=0; i<20; i++)
            {
                for(int j=0; j<5; j++)
                {
                    if(j==0)
                    {
                        if(ans==a1[i])
                        {
                            flag = true;
                            break;
                        }
                        else if(!s.count(a1[i]))
                        {
                            s.insert(a1[i]);
                            k++;
                            continue;
                        }
    
                    }
    
                    if(j==1)
                    {
                        if(ans==a2[i])
                        {
                            flag = true;
                            break;
                        }
                        else if(!s.count(a2[i]))
                        {
                            s.insert(a2[i]);
                            k++;
                            continue;
                        }
    
                    }
                    if(j==2)
                    {
                        if(ans==a3[i])
                        {
                            flag = true;
                            break;
                        }
                        else if(!s.count(a3[i]))
                        {
                            s.insert(a3[i]);
                            k++;
                            continue;
                        }
    
                    }
                    if(j==3)
                    {
                        if(ans==a4[i])
                        {
                            flag = true;
                            break;
                        }
                        else if(!s.count(a4[i]))
                        {
                            s.insert(a4[i]);
                            k++;
                            continue;
                        }
    
                    }
    
                    if(j==4)
                    {
                        if(ans==a5[i])
                        {
                            flag = true;
                            break;
                        }
                        else if(!s.count(a5[i]))
                        {
                            s.insert(a5[i]);
                            k++;
                            continue;
                        }
    
                    }
                }
                if(flag)
                    break;
            }
    
            int kk = 1;
            for(int i=0;i<20;i++) {
                if(ans==ec[i])
                    break;
                else if(!s.count(ec[i])) {
                    kk++;
                    s.insert(ec[i]);
                }
            }
    
            int yy = -1;
            for(int i=0;i<=g;i++) {
                int x = g-i;
                int y = i;
                if(x<k&&y<kk)
                {
                    yy = y;
                    break;
                }
            }
    
            if(yy==-1)
                printf("Case #%d: ADVANCED!
    ",kase++);
            else printf("Case #%d: %d
    ",kase++,yy);
    
        }
        return 0;
    }
    

    Problem H:

    题意:n个工程项目,m 个工程师,工程师会一些项目,每一个工程项目需要一些工程项目,每个工程师只能去一个工程,求最多能完成多少个工程项目;

    分析:n,m<=10 可以考虑集合上DP,考虑每一个工程师选或不选,但是不能直接用人数状态去循环遍历可以完成哪些项目;要优化,预处理,第i个项目,有哪些人数状态可以完成,然后dp的时候,只要考虑这两个集合是否有包含关系,改成了一重循环;

    tip: 值得注意的是,最后的结果不是max(dp(i,(1<<m)-1)) ,而是人数的s状态要考虑。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int c[20][10],d[20][10];
    int p[120];
    
    int dp[20][1<<11];
    
    int main()
    {
        int t;
        int n,m;
        scanf("%d",&t);
        int kase = 1;
        while(t--)
        {
            scanf("%d%d",&n,&m);
            vector<int> a[20];
            memset(dp,0,sizeof(dp));
    
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&c[i][0]);
                for(int j=1; j<=c[i][0]; j++)
                    scanf("%d",&c[i][j]);
            }
    
            for(int i=0; i<m; i++)
            {
                scanf("%d",&d[i][0]);
                for(int j=1; j<=d[i][0]; j++)
                    scanf("%d",&d[i][j]);
            }
    
            for(int i=1; i<=n; i++)
            {
                for(int s=0; s<(1<<m); s++)
                {
                    int cnt=0;
                    memset(p,0,sizeof(p));
                    for(int k=0; k<m; k++)
                    {
                        if(s&(1<<k))
                        {
                            cnt++;
                            for(int j=1; j<=d[k][0]; j++)
                                p[d[k][j]]=1;
                        }
                    }
    
                    int flag=1;
                    for(int j=1; j<=c[i][0]; j++)
                        if(p[c[i][j]]==0) flag=0;
                    if(flag) a[i].push_back(s);     //第i个项目,有哪些人完成
                }
            }
    
            for(int i=1; i<=n; i++)
            {
                for(int s=0; s<(1<<m); s++)
                {
                    for(int j=0; j<a[i].size(); j++)
                    {
                        if((s|a[i][j])==s)
                        {
                                dp[i][s]=max(dp[i-1][s-a[i][j]]+1,dp[i][s]);
                        }
                    }
                    dp[i][s]=max(dp[i][s],dp[i-1][s]);
                }
            }
    
            printf("Case #%d: %d
    ",kase++,dp[n][(1<<m)-1]);
    
        }
        return 0;
    }
  • 相关阅读:
    POJ 2253 Frogger
    C++map函数的用法
    蓝桥杯 幂方分解
    蓝桥杯 危险系数
    POJ 2234 Matches Game
    POJ 1852 Ants
    POJ 1144 Network
    POJ1419 Graph Coloring
    poj 2573 Bridge(有A、B、C、D四个人,要在夜里过一座桥……)
    小知识(输出源文件的标题和目前执行行的行数)
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7137556.html
Copyright © 2020-2023  润新知