zoukankan      html  css  js  c++  java
  • Google Kick Start 2020 Round A

    Allocation

    题意

    N个房子出售,每个卖Ai刀,现有B刀资金,求最多买多少个。

    思路

    贪心,排序后从小到大买

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAX=1e5+5;
    
    int a[MAX];
    
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--)
        {
            int n,b,res=0;
            scanf("%d%d",&n,&b);
            for(int i=0;i<n;i++)
                scanf("%d",&a[i]);
            sort(a,a+n);
            for(int i=0;i<n;i++)
            {
                if(a[i]>b)break;
                b-=a[i];
                res++;
            }
            printf("Case #%d: %d
    ",++cas,res);
        }
    }
    

    Plates

    题意

    n摞盘子,每一摞有k个,每个盘子有一定价值,现在要选p个盘子,要求每次只能选一摞的从上到下的一部分,求如何选使得总价值最大

    思路

    DPdp[i][j] 表示前i摞中共选j个可得的最大价值,转移枚举当前摞选m个(选前缀),然后由 dp[i-1][j-m] 转移而来

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAX=1505;
    
    int a[MAX][MAX],pre[MAX][MAX],dp[MAX][MAX];
    
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--)
        {
            int n,p,m;
            scanf("%d%d%d",&n,&m,&p);
            memset(dp,0,sizeof dp);
            for(int i=1; i<=n; i++)
                for(int j=1; j<=m; j++)
                {
                    scanf("%d",&a[i][j]);
                    pre[i][j]=pre[i][j-1]+a[i][j];
                }
            for(int i=1; i<=n; i++)
                for(int j=0; j<=min(i*m,p); j++)
                    for(int k=0; k<=min(j,m);k++)
                        dp[i][j]=max(dp[i][j],dp[i-1][j-k]+pre[i][k]);
            printf("Case #%d: %d
    ",++cas,dp[n][p]);
        }
    }
    

    Workout

    题意

    给一个单调递增序列,有n个数,设D值为此序列每个数与相邻数的差的最大值,现在可以在保证序列单调增的情况下,在此序列任意位置插入任意大小的k个数,求如何使得此序列D值最小,求出最小D值。

    思路

    容易想到,可以在两个数中间插a-1个数,使得两者差变为原来的a分之一(向上取整),先处理出原序列所有差,然后二分答案,再通过上述结论检测此答案是否可行,最后得到最小值。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAX=1e5+5;
    
    int n,k,a[MAX],ch[MAX];
    
    bool check(int x)
    {
        int tot=k;
        for(int i=1; i<n; i++)
        {
            if(ch[i]<=x)continue;
            for(int j=1;; j++)
            {
                int cur=(ch[i]+j)/(j+1);
                if(cur<=x)
                {
                    if(j<=tot)tot-=j;
                    else return 0;
                    break;
                }
            }
        }
        return 1;
    }
    
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--)
        {
            int L=1,R=-1,res;
            scanf("%d%d",&n,&k);
            for(int i=0; i<n; i++)
                scanf("%d",&a[i]);
            for(int i=1; i<n; i++)
                ch[i]=a[i]-a[i-1],R=max(R,ch[i]);
            while(L<=R)
            {
                int mid=(L+R)>>1;
                if(check(mid))
                {
                    res=mid;
                    R=mid-1;
                }
                else
                    L=mid+1;
            }
            printf("Case #%d: %d
    ",++cas,res);
        }
    }
    

    Bundling

    题意

    n个字符串,要求分成大小为k的若干组(nk的倍数),每组的得分为该组所有字符串的最长公共前缀长度。求如何使得得分最大化,求出最大得分。

    思路

    显然公共前缀越长越好,所以贪心,找公共前缀最长的能分成一组的就分成一组,建一棵字典树,记录以某前缀开头的字符串数量。然后在字典树上贪心寻找尽可能深的,足够分成一组的前缀(即寻找以此前缀开头的字符串数量大于等于k的前缀),然后用深度更新答案,再返回已经用过的数量给父亲,更新父亲的数量。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAX=2e6+6;
    typedef long long ll;
    
    int nxt[MAX][26],sum[MAX],cnt,n,k;
    ll res;
    char ss[MAX];
    
    void ins(char *s)
    {
        int p=0,len=strlen(s);
        sum[p]++;
        for (int i=0; i<len; i++)
        {
            int c=s[i]-'A';
            if(!nxt[p][c])nxt[p][c]=++cnt;
            p=nxt[p][c];
            sum[p]++;
        }
    }
    int dfs(int x,int d)
    {
        int ssum=0,cur=0;
        for(int i=0;i<26;i++)
            if(nxt[x][i])
                ssum+=dfs(nxt[x][i],d+1);
        sum[x]-=ssum;
        if(sum[x]>=k)
        {
            cur=sum[x]/k;
            res+=d*cur;
            sum[x]%=k;
        }
        return ssum+cur*k;
    }
    void init()
    {
        memset(nxt,0,sizeof nxt);
        memset(sum,0,sizeof sum);
        cnt=0;
        res=0;
    }
    
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&k);
            init();
            for(int i=0;i<n;i++)
            {
                scanf("%s",ss);
                ins(ss);
            }
            dfs(0,0);
            printf("Case #%d: %lld
    ",++cas,res);
        }
    }
    
  • 相关阅读:
    POJ 1681 Painter's Problem(高斯消元法)
    HDU 3530 Subsequence(单调队列)
    HDU 4302 Holedox Eating(优先队列或者线段树)
    POJ 2947 Widget Factory(高斯消元法,解模线性方程组)
    HDU 3635 Dragon Balls(并查集)
    HDU 4301 Divide Chocolate(找规律,DP)
    POJ 1753 Flip Game(高斯消元)
    POJ 3185 The Water Bowls(高斯消元)
    克琳:http://liyu.eu5.org
    WinDbg使用
  • 原文地址:https://www.cnblogs.com/cryingrain/p/12569372.html
Copyright © 2011-2022 走看看