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\n",++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\n",++cas,dp[n][p]);
    }
}

Workout

题意

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

思路

容易想到,可以在两个数中间插a个数,使得两者差变为原来的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\n",++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\n",++cas,res);
    }
}

原文地址:https://www.cnblogs.com/cryingrain/p/12569372.html

时间: 2024-07-30 18:24:10

Google Kick Start 2020 Round A的相关文章

Google Kick Start 2018 Round C Planet Distance

思想: 1.用邻接表建图. 2.建完图之后,先把图中的环给找出来. 怎么找呢? (1)先统计每一个节点的度.   (2)统计完了之后,通过使用队列,把度为1 的点给剔除.每剔除一个,所谓剔除其实就是用一个dis[] 数组来做标记,其相应的邻居的度减一,如果该邻居的度为1了,那么把它加到队列里,重复上述过程,直到队列为空. (3)最后统计一下,剩下的就是环里的元素. 3.再对环里的元素用BFS搞一下,往外扩散.记录距离. AC 代码如下: import java.util.ArrayList; i

Google Kickstart 2020 Round A: Plates Solution

Problem Statement Problem Dr. Patel has N stacks of plates. Each stack contains K plates. Each plate has a positive beauty value, describing how beautiful it looks. Dr. Patel would like to take exactly P plates to use for dinner tonight. If he would

Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)

Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall with a window separates adjacent cells, and

Round A 2020 - Kick Start 2020

Allocation 题意:n(1e5)个数,选出尽可能多的数使他们总和小于等于b. 思路:排序,尽可能取小. 1 #include<bits/stdc++.h> 2 #define LL long long 3 #define dl double 4 void rd(int &x){ 5 x=0;int f=1;char ch=getchar(); 6 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 whi

Google Code Jam 2014 Round 2回顾和分析

回顾 比赛开始网络就一直在抽风,不知道宿舍网渣还是有人攻击服务器.刷了n遍n久刷出了题目.提交A小case的时候眼睁睁看着时间过去,却提交不上,这破网.最后A题B题还是解决了,C题扫了一眼,读都没读,就奔D题去了,因为我看到了熟悉的trie这个单词,加之看到小case只有9分,判断小case应该比较容易.前面因为网络浪费了很多时间,加之从未编过trie的程序,只能临时上网翻书去学,最后D小这个可以很容易暴力解的问题也没编完. 最终的rank是13xx,考虑到在这次GCJ之前从未接触过编程竞赛,而

google kick start in March

https://codingcompetitions.withgoogle.com/kickstart/round/0000000000050e01/000000000006987d 二分思想太牛逼!!!! 原文地址:https://www.cnblogs.com/waldenlake/p/10649624.html

Google Code Jam 2014 Round 1B Problem B

二进制数位DP,涉及到数字的按位与操作. 查看官方解题报告 #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; #define MAX_LEN 50 long long A, B, K; int a[MAX_LEN], b[MAX_LEN], k[MAX_LEN]; long long memoize[MAX_LEN]

Google Code Jam 2016 Round 1B B

题意:给出两个数字位数相同,分别中间有若干位不知道,用问号表示.现在要求补全这两个数字,使得差值的绝对值最小,多解则取第一个数字的值最小的,再多解就取第二个数字最小的. 分析: 类似数位dp,但是很多状态可以直接得出最终解,个别状态需要状态转移. 我们从高位到低位依次确定两个数的每个位是几.一旦确定了两个数的一个位不一样,则可以立即将小的一方的后续问号全部写9,大的一方后续问号全部写0.这样才能让差值最小. 那我们观察每个位的时候要如何确定其值呢?分如下几种情况. 1.两个数的该位都是问号,那么

Google Code Jam 2016 Round 1C C

题意:三种物品分别有a b c个(a<=b<=c),现在每种物品各选一个进行组合.要求每种最和最多出现一次.且要求任意两个物品的组合在所有三个物品组合中的出现总次数不能超过n. 要求给出一个方案,使得我们能够生成的组合数最多. 分析: 首先我们可以简单的处理一种情况,就是c<=n的情况. 因为我们枚举出了所有组合,那么两物品的出现次数的最大值不会超过c,因为A种和B种的每对组合都会在其中出现c次,其余两个的组合出现次数更少. 所以这种情况一定不会超过n,我们只需要枚举所有组合即可. 然而