2021.01.19学习笔记

8:00~8:05 学习打卡

梦想是黑暗中的一盏名灯,能照亮跋涉者心中的每一个角落。

8:20~11:20 刷题

刷题总结:
复习题题组

问题 H: Home Work
描述
临近开学了,大家都忙着收拾行李准备返校,但I_Love_C却不为此担心! 因为他的心思全在暑假作业上:目前为止还未开动(-_-!!还以为他有多冷静呢)。
暑假作业是很多张试卷,我们这些从试卷里爬出来的人都知道,卷子上的题目有选择题、填空题、简答题、证明题等。 而做选择题的好处就在于工作量很少,但又因为选择题题目都普遍很长。 如果有5张试卷,其中4张是选择题,最后一张是填空题,很明显做最后一张所花的时间要比前4张长很多。 但如果你只做了选择题,虽然工作量很少,但表面上看起来也已经做了4/5的作业了。 I_Love_C决定就用这样的方法来蒙混过关。
他统计出了做完每一张试卷所需的时间以及它做完后能得到的价值(按上面的原理,选择题越多价值当然就越高咯)。 现在就请你帮他安排一下,用他仅剩的一点时间来做最有价值的作业。
格式
输入格式
测试数据包括多组。 每组测试数据以两个整数M,N(1≤M≤20, 1≤N≤10000)开头,分别表示试卷的数目和I_Love_C剩下的时间。 接下来有M行,每行包括两个整数T,V(1≤T≤N,0<V<10000),分别表示做完这张试卷所需的时间以及做完后能得到的价值! 输入以0 0结束。写试卷的时间可能为0!!!
输出格式
对应每组测试数据输出I_Love_C能获得的最大价值。
保留小数点2位

样例
样例输入 Copy
4 20
4 10
5 22
10 3
1 2
0 0
样例输出 Copy
37.00
提示
float的精度可能不够。 你应该使用double类型。

那题在今早上排查中找出错误。原来试卷数量可以为0,这样一来我的 set迭代器 有可能就会出现非法访问下面是未改之前的代码:

       while (n > 0 && it != a.end())
        {
            ans += it->v;
            n -= it->t;
            it++;
        }
        it--;
        if (n < 0)
            ans += n * (it->v / it->t);
        printf("%.2lf\n", ans);

其中a是set容器,如果a是空的,那么我的那个it–就会出问题,所以我改成了下面这个:

        while (n > 0 && it != a.end())
        {
            ans += it->v;
            n -= it->t;
            it++;
        }
        if (n < 0)
        {
            it--;
            ans += n * (it->v / it->t);
        }
        printf("%.2lf\n", ans);

这样就避免了迭代器的非法访问。
下面是完整代码:

#include <bits/stdc++.h>
using namespace std;
struct node
{
    double t = 0, v = 0;
    bool operator<(const node &a) const
    {
        if (this->t == 0)
            return true;
        if (a.t == 0)
            return false;
        return this->v / this->t > a.v / a.t;
    }
};
int main(void)
{
    double m, n;
    while ((cin >> m >> n) && !(m == 0 && n == 0))
    {
        set<node> a;
        node x;
        for (int i = 0; i < m; i++)
        {
            cin >> x.t >> x.v;
            a.insert(x);
        }
        auto it = a.begin();
        double ans = 0;
        while (n > 0 && it != a.end())
        {
            ans += it->v;
            n -= it->t;
            it++;
        }
        if (n < 0)
        {
            it--;
            ans += n * (it->v / it->t);
        }
        printf("%.2lf\n", ans);
    }
    return 0;
}

问题 E: 刷题的兄弟俩
描述
众所周知,lbg和gbl是一对兄弟,他们时常位居刷题榜前列,为了赢得学妹的芳心
他们决定进行一场刷题比赛,他们找来了1000000000000000道题,比赛的规则是
1、一道题只能归一个人所有(这题被gbl过了,lbg就接着往后刷);
2、从第一题开始往后刷;
3、谁先刷完最后一题谁就赢了;
4、只有一台机子,每次只能有一个人上机;
5、一次上机刷超过 m (1<=m<=100) 道题会被系统判定为舞弊;
因为lbg和gbl都很聪明,所以每次上机都不会舞弊,而且所有的题他们都会做。
这时比赛已经进行到了晚上就要断网了,还剩 n (0<n<1000000)道题。
假设lbg先上机,请问谁能获得小学妹的芳心?

格式

输入格式

输入数据首先包含一个正整数T,表示包含T组测试用例,然后是T行数据,每行包含两个正整数n,m,n和m的含义参见上面提到的规则。

输出格式

对于每组测试数据,如果lbg能获得小学妹的芳心,请输出字符串"lbg",
如果gbl能获得小学妹的芳心,请输出字符串"gbl",每个实例的输出占一行。

样例

样例输入 Copy

2

8 10

11 10

样例输出 Copy

lbg
gbl

这题稍微分析一下,就是一个简单的博弈,抽牌时,牌的数量如果是M+1,那就必输,因为无论怎么刷,下一把的人绝对能把题刷完。如果是M+1的倍数,也必输,因为刷完后,后手总能把题的数量弄成M+1的倍数,最后剩下M+1:

#include <bits/stdc++.h>
using namespace std;
int main(void)
{
    int t;
    cin >> t;
    while (t--)
    {
        int n, m;
        cin >> n >> m;
        if (n % (m + 1))
            cout << "lbg" << endl;
        else
            cout << "gbl" << endl;
    }
    return 0;
}

问题 F: 打牌的兄弟俩
描述
自从上次gbl刷题输给lbg之后gbl就一直不服气,gbl想着laozi刷题刷不过你,laozi打牌还打不过你?
于是怒气冲冲的冲到小学妹的宿舍把lbg叫出来,“我不服,咱俩再来比一场,就比打牌,小学妹你来做裁判”
作为软件工程的学生,lbg打牌的时候可没忘记专业,于是lbg制定了如下规则: 1、总共n张牌 2、双方轮流抓牌
3、每人每次抓牌的个数只能是2的幂次(如:1,2,4,8,16…) 4、抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
众所周知,lbg和gbl都是足够聪明,并且每次都是lbg先抓牌,请问谁能赢呢?

格式
输入格式
输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000000)。

输出格式
如果lbg能赢的话,请输出“lbg”,否则请输出“gbl”,每个实例的输出占一行。

样例
样例输入 Copy
1 3
样例输出 Copy
lbg gbl

基础博弈,谁面临3的倍数,谁输,因为3必输,牌的数量可以写成3*n+a(0<=a<=2),先手如果不是3的倍数,那他可以把牌一直控制成3的倍数,最后后手面临的是3,则后手败。反之先手败。

#include <bits/stdc++.h>
using namespace std;
int main(void)
{
    int n;
    while(cin>>n)
    if(n%3==0)cout<<"gbl"<<endl;
    else cout<<"lbg"<<endl;
    return 0;
}

问题 D:
签到送气球 描述
ACM-ICPC程序设计大赛是大学级别最高的脑力竞赛,素来被冠以"程序设计的奥林匹克"的尊称。大赛至今已有近40年的历史,是世界范围内历史最悠久、规模最大的程序设计竞赛。比赛形式是:从各大洲区域预赛出线的参赛队伍,于指定的时间、地点参加世界级的决赛,由1个教练、3个成员组成的小组应用一台计算机解决7到13个生活中的实际问题。在正式赛场中,一个队伍每解决一个新的问题就会有一个相应的气球作为奖励送到这个队伍所在的位置。
LBG作为这次ACM-ICPC的志愿者,当然是时刻关注着场上的过题情况的,每当有一个队伍通过新的问题的时候,他就会马上送上气球。但由于参赛队伍实在是太多了,他也不清楚每个队伍得到了多少个气球。在比赛结束之后,他拿到了一份这场比赛的题目提交情况,他想知道现场参加比赛的队伍每个队伍能获得多少个气球,聪明的你能帮帮他吗?

格式
输入格式
第一行包含一个整数T(T<=10),表示总共有T组测试样例;
第二行输入一个整数n,m;
n表示有多少个队伍参加这次的比赛(1<=n <= 50); m表示有多少条提交记录(1<=m<=1000);
接下来输入m行,每行输入格式如下:
team_id problem_id submit_status team_id代表着队伍的编号(1 <= team_id <=n);
problem_id代表着题目编号(为A~M的大写字母);
submit_status代表着这个题目提交的结果(可能是"AC",“PE”,“TLE”,“MLE”,“WA”,“RE”,"CE"其中的一种)。

输出格式
对于每组样例 第一行输出一行“Case #x:”,x表示当前为第几组样例(详细见样例);
第二行输出n个数(每两个数之间用空格隔开)代表着第 i 个队可以获得的气球数量。(注意不要在每一行的末尾输出多余的空格)。

样例
样例输入 Copy
1
5 10
1 A WA
1 A AC
2 A AC
3 C TLE
2 C TLE
1 C AC
3 A AC
4 A AC
1 A AC
5 A WA
样例输出 Copy
Case #1:
2 1 1 1 0
提示
每次提交只有提交结果是"AC"的题目才可以得到气球。如果一个队伍如果通过同一个题目多次,他也只能获得一个气球。

签到题,没有啥算法:

#include <bits/stdc++.h>
using namespace std;
struct team
{
    bool problem[256] = {false};
    int ac = 0;
};
int main(void)
{
    int t;
    cin >> t;
    for (int i = 1; i <= t; i++)
    {
        team teams[60];
        int n, m;
        cin >> n >> m;
        for (int j = 1; j <= m; j++)
        {
            int tid;
            char proid;
            string sub;
            cin >> tid >> proid >> sub;
            if (sub == "AC")
            {
                if (teams[tid].problem[proid] == false)
                    teams[tid].ac++;
                teams[tid].problem[proid] = true;
            }
        }
        cout << "Case #" << i << ":\n";
        for (int i = 1; i <= n; i++)
            cout << teams[i].ac << ' ';
        cout << endl;
    }
    return 0;
}

13:30~16:30 学习算法书《挑战程序设计竞赛》第2版

一、栈和队列
二、深度优先搜索(栈)
三、广度优先搜索(队列)
四、剪枝(去掉无用功)
五、贪心算法
六、DP动态规划(经典背包问题)

17:00~18:00 背单词、学英语

18:30~19:30 预备役群听课(讲二分法)

结束!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值