牛客寒假算法集训营1 补题

标题迷惑大赏

A、World Final? World Cup! 

题目描述

众所周知,2022年是四年一度的世界杯年,那么当然要整点足球题。本题需要你模拟一次点球大战。
假设对战双方为A和B,则点球大战中双方会按照ABABABABAB方式来罚点球,即两队交替罚点球、各罚五次、A队先罚。点球有罚进和罚不进两种结果,罚中的一方加一分。
其判断胜负的规则为得分多者获胜,而若在罚完某一球后(无论是哪队罚的),当前双方比分已经使得无论之后的罚球结果如何都不会影响比赛的结果,则此时比赛结束。特别地,若直到10球踢完都没有分出胜负则再继续加踢更多的点球。
现在,给出接下来双方10个点球的结果,你需要判断点球大战会在踢完几球时结束,或指出10球内没有分出胜负。

输入描述:

输入第一行包含一个整数T(1≤T≤1024),表示样例组数。
每组测试用例包括一个长度为10的字符串S,第i个字符表示第i个点球的结果,0表示罚不进、1表示罚进,保证不会出现其他字符。

输出描述:

对每组测试用例,输出一个整数,表示点球大战会在第几回合结束,若10轮之内没有分出胜负,输出−1。

简单模拟:

(1)当剩余场次全赢,都无法取胜那么,即可退出循环,得到点球场次

(2)当遍历完整个字符串时,处于平局,即可输出-1

#include<iostream>

using namespace std;

int t;
string s;

int main()
{
    cin >> t;
    while(t --)
    {
        cin >> s;
        // 偶是A
        // 奇是B
        int A = 0 , B = 0;
        int n = s.size();
        int res = 0;
        for(int i = 0;i < n;i ++)
        {
            res = i + 1;
            if(s[i] == '1')
            {
                if(i & 1) B ++;
                else A ++;
            }
            if(A + (n - res) / 2 < B) break;
            if((n - res) % 2 == 0) 
            {
                if(B + (n - res) / 2 < A) break;
            }
            else 
            {
                if(B + (n - res) / 2 + 1 < A) break;
            }
        }
        if(A == B) res = -1;
        cout << res << endl;
    }
    return 0;
}

C、现在是,学术时间
        北京IT大学(BIT)计算机学院为了在下一轮学科评估中让计算机学科获得A+的评定结果,进行了如引进强大的老师、加强课程之类、提高授课质量等多方面的努力。而为了提高学科评估中,学术成果一项的得分,计算机学院的院长打算通过重新分配论文的方式使得学院里所有教授的H指数值之和尽可能大。具体来说,H指数用于粗略的评估一位教授的学术水平。一位教授可以发表多篇论文,每篇论文有一个引用量。定义一位教授的H指数为使得"该教授发表的所有论文中,有至少H篇论文的引用量大于等于H"这一命题成立的最大的H。现在,院长发现学院里的每位老师当前的发表文章数都为000,且恰好每人都有一篇写好的论文未发表,由于院长很懂学术界,他也可以准确的预知到每篇文章发表后的引用量。院长决定以最优的方式重新分配这些论文,他可以任意指定一篇论文由哪位教授发表。规定每篇论文只能被一位教授发表,一位教授可以发表多篇论文。假设重新分配并发表后第i位教授的H指数为hi,院长希望最大化Σhi,即所有教授的H指数之和最大。请你帮院长计算出这一最大的值为多少。

输入描述:

输入第一行为一个正整数T(1≤T≤105),表示样例组数。
每组样例包括两行。
第一行是一个正整数n(1≤n≤105),表示北京IT大学计算机学院的教授数量;第二行包括n个非负整数,第i个数字ai(0≤ai≤109)表示第i位教授写好但未发表的文章在发表后会获得的引用量。

输出描述:

对于每组样例,输出一个整数,表示Σhi​最大的值为多少。

可以使用贪心的思想

和最大即就是使每一个h最大即可,进一步思考即就是尽可能的选择论文,只有当引用量处于0的时候,无法增加最大值。因此答案一定就是n - 0的个数

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 1e5 + 10;
int t , n;
int a[N];

int main()
{
    scanf("%d" , &t);
    while(t --)
    {
        scanf("%d" , &n);
        int res = n;
        for(int i = 0;i < n;i ++)
        {
            scanf("%d" , &a[i]);
            if(!a[i]) res --;
        }
        printf("%d\n" , res);
    }
    return 0;
}

H、本题主要考察了DFS
        PTA的拼图由n∗n个大小为1∗1的拼图块组成,每个拼图块都是在正方形的1∗1拼图块基础上生成的,生成方法为:对于每一条边,可以选择不变、向里削出一个半圆形的缺口、向外补上一个半圆形的凸出三种操作之一。因此,一个拼图块可以由一个长度为444的字符串描述,四个字符分别表示上、右、下、左四条边进行的操作,上述三种操作依次记为0,1,2下图的左图为一个2∗2的拼图。而右图为左图中左上角的一块1∗1拼图的字符串描述,由于其上、右、下、左进行的操作分别为不变、凸出、缺口、不变,因此这块拼图对应的字符串为0210。

输入描述:

输入第一行是一个整数T(1≤T≤100),表示测试用例组数。

对于每组测试用例:

第一行为一个正整数n(2≤n≤20),表示拼图的大小。

接下来n^2-1行,每行一个长度为4的字符串,表示一块拼图正面朝上、未经旋转的形状。保证字符串中只含0,1,2三种字符。

输入数据保证n^2-1块拼图是从一个合法的n∗n拼图中按如题面所述的过程获得的。

分析:不进行操作的每一块拼图的价值是10,因此一共的价值就是10*n*n用已知的拼图价值一减去即使需要的拼图的价值

#include<iostream>

using namespace std;

int t;
int main()
{
    cin >> t;
    while(t --)
    {
        int n;
        cin >> n;
        int res = 0;
        for(int i = 1;i <= n * n - 1;i ++)
        {
            string s;
            cin >> s;
            res += 10;
            for(int j = 0;j < s.size();j ++)
                if(s[j] == '1') res --;
                else if(s[j] == '2') res ++;
        }
        cout << 10 * n * n - res << endl;
    }
    return 0;
}

L、本题主要考察了运气

没什么说的输出32即可


M、本题主要考察了找规律

小波奇日常想太多,她认为分仙贝时好感度的变化是有规律的,不过并不是给的仙贝越多,好感度上升的就越多,而是应该看小波奇给出的仙贝数与她当前手里总仙贝的比值。也就是说,若小波奇当前还剩下x(x>0)个仙贝,并给了一位朋友y个仙贝(x,y都为整数),则这位朋友对小波奇的好感度将增加y/x(这个值可以为小数)。

现在,小波奇可以任意安排送仙贝的顺序和每次送仙贝的个数,但不能给同一个人送两次仙贝,允许最后手中还有剩余的仙贝,允许最终有朋友没有分到仙贝。社恐的朋友非常重要,所以请你帮助小波奇算一算,在最优送仙贝策略下,小波奇和所有人的好感度之和最大为多少(假设初始小波奇和所有人好感度都为0)。

分析:不要被题目迷惑,是一道经典的dp

集合表示:从前i个人中选,送出仙贝个数为j的最大值

状态计算:f[i , j] = max\left\{\begin{matrix} & f[i , j] & \\ & f[i - 1 , j - k] + k / j & \end{matrix}\right.

#include<iostream>

using namespace std;

const int N = 510;
int n , m;
double f[N][N];

int main()
{
	cin >> n >> m;
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= m;j ++)
			for(int k = 0;k <= j;k ++)
				f[i][j] = max(f[i][j] , f[i - 1][j - k] + 1.0 * k/j);
	
	printf("%.6lf" , f[n][m]); 
	return 0;
}

K、主要考察dp

给定由0和1组成的长度为n的字符串,要求其中有m个1。定义一段长度为3的连续子区间中,如果1的个数大于0的个数,则该区间为坏的。请问所有满足条件的字符串中,坏区间最少有多少?

分析:跟dp没有什么关系,我是用的贪心

构造100100....1111这样的序列,可以保证坏区间最少

#include<iostream>

using namespace std;

int n , m;

int main()
{
    cin >> n >> m;
    int one = m , zero = n - m;
    //100100 ... 11111
    zero /= 2;
    if(!zero) cout << n - 2 << endl;// 表示没有100 全为1
    else cout << max(0 , one - zero - 1); // 剩余的1的个数就是总数减去凑100的1的个数
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值