软件学院PTA天梯赛初赛选拔赛题解

目录

7-2 生肖确定(模拟)

AC代码:

7-3 韩信点兵(模拟)

AC代码:

7-4 程序员买包子(模拟)

AC代码:

7-5 h0078. 蛇形矩阵变形

AC代码:

7-6 军事体能成绩统计(升级版)(模拟)

AC代码:

7-7 铺草坪提高版(思维)

AC代码:

7-8 FJCC-GPLT(模拟)

AC代码:

7-9 看照片找基友(并查集)

AC代码:

7-10 小猫爬山(dfs+剪枝)

AC代码:

7-11 h0075. 射击游戏(dfs)

AC代码:

7-12 令人抓狂的四则运算(大模拟)

7-13 寻宝图(BFS+连通块)

7-14 完美树(树形DP,状态机,贪心)


7-2 生肖确定(模拟)

2023年是兔年,1年后(2024年)是龙年,1年前(2022年)是虎年。那么对于给定的一个整数n,请确定2023年之前(n为负数)或之后(n为正数)∣n∣年的结果年份及其对应的生肖(以英文单词表示,详见最后的提示)。

输入格式:

首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试输入1个整数n (−2023<n≤10000,n≠0)。

输出格式:

对于每组测试,在一行上输出结果年份及其对应的生肖,之间以一个空格间隔。

输入样例:

3
-1
1
2

输出样例:

2022 tiger
2024 dragon
2025 snake

提示:

鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪等十二生肖相应的英文单词如下:
rat、ox、tiger、rabbit、dragon、snake、horse、goat、monkey、rooster、dog、pig

思路:简单模拟题定义一个字符串数组把十二生肖对应的英文单词分别记录进去,随后依据题意进行模拟即可

AC代码:

#include <bits/stdc++.h>

using namespace std;

vector<string> item = {"rat", "ox", "tiger", "rabbit", "dragon", "snake", "horse", "goat", "monkey", "rooster", "dog", "pig"};

void solve() {
    int i, j, k, n, index = 3;
    cin >> n;
    int ans = 2023 + n;
    if (n < 0) {
        while (n++) {
            index--;
            if (index == -1) index = 11;
        }
    } else {
        while (n--) {
            index++;
            if (index == 12) index = 0;
        }
    }
    cout << ans << " " << item[index] << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    system("pause");
    return 0;
}

7-3 韩信点兵(模拟)

在中国数学史上,广泛流传着一个“韩信点兵”的故事:韩信是汉高祖刘邦手下的大将,他英勇善战,智谋超群,为汉朝建立了卓越的功劳。据说韩信的数学水平也非常高超,他在点兵的时候,为了知道有多少兵,同时又能保住军事机密,便让士兵排队报数:

  • 按从1至5报数,记下最末一个士兵报的数为1;
  • 再按从1至6报数,记下最末一个士兵报的数为5;
  • 再按从1至7报数,记下最末一个士兵报的数为4;
  • 最后按从1至11报数,最末一个士兵报的数为10;

请编写程序计算韩信至少有多少兵。

输入格式:

本题无输入

输出格式:

输出韩信至少拥有的士兵人数。

AC代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int i, j, k, n;
    n = 0;
    while (++n) {
        if (n % 5 == 1 && n % 6 == 5 && n % 7 == 4 && n % 11 == 10) break;
    }
    cout << n << endl;

    system("pause");
    return 0;
}

7-4 程序员买包子(模拟)

这是一条检测真正程序员的段子:假如你被家人要求下班顺路买十只包子,如果看到卖西瓜的,买一只。那么你会在什么情况下只买一只包子回家?
本题要求你考虑这个段子的通用版:假如你被要求下班顺路买 N 只包子,如果看到卖 X 的,买 M 只。那么如果你最后买了 K 只包子回家,说明你看到卖 X 的没有呢?

输入格式:

输入在一行中顺序给出题面中的 N、X、M、K,以空格分隔。其中 N、M 和 K 为不超过 1000 的正整数,X 是一个长度不超过 10 的、仅由小写英文字母组成的字符串。题目保证 N≠M。

输出格式:

在一行中输出结论,格式为:

  • 如果 K=N,输出 mei you mai X de
  • 如果 K=M,输出 kan dao le mai X de
  • 否则输出 wang le zhao mai X de.
    其中 X 是输入中给定的字符串 X。

输入样例1:

10 xigua 1 10

输出样例1:

mei you mai xigua de

输入样例2:

10 huanggua 1 1

输出样例2:

kan dao le mai huanggua de

输入样例3:

10 shagua 1 250

输出样例3:

wang le zhao mai shagua de

AC代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n, m, k;
    string x;
    cin >> n >> x >> m >> k;
    if (k == n) cout << "mei you mai " << x << " de" << endl;
    else if (k == m) cout << "kan dao le mai " << x << " de" << endl;
    else cout << "wang le zhao mai " << x << " de" << endl;

    system("pause");
    return 0;
}

7-5 h0078. 蛇形矩阵变形

现在给你一个n*n的初始全零的矩阵,请你将其按以下方法填数:

但是这样子太过简单,所以每一次操作会选择一个子矩阵,请你在其子矩阵上进行填数,并在最后输出整个矩阵

输入格式:

第一行两个整数n,m,表示矩阵的大小和操作次数(n≤2000,m≤3000)接下来m行,每行输入三个正整数x,y,k,表示在以(x,y)为左上角,边长为k的方阵内填数(1≤x,y≤n,max(x+k−1,y+k−1)≤n)

输出格式:

输出一个n*n的矩阵,每个整数占5个字节。

输入样例:

3 2
1 1 3
2 2 2

输出样例:

    1     2     3
    6     1     2
    7     4     3

思路:按题意进行模拟即可,在进行行数变换的时候可以定义一个bool类型的变量,可以用来区分此行是正方向还是负方向

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = (int)2e3 + 10;
vector<vector<int>>nums(maxn, vector<int>(maxn, 0));

int n, m;

void solve() {
    int i, j, k, x, y;
    int item = 1;
    bool flag = true;
    cin >> x >> y >> k;
    x--, y--;
    for (i = x; i < x + k; i++) {
        if (flag)
            for (j = y; j < y + k; j++) nums[i][j] = item++;
        else
            for (j = y + k - 1; j >= y; j--) nums[i][j] = item++;
        flag = !flag;
    }
}

int main()
{
    int i, j, k;
    cin >> n >> m;
    while (m--) {
        solve();
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            if (j != 0) cout << " ";
            printf("%5d", nums[i][j]);
        }
        cout << endl;
    }

    system("pause");
    return 0;
}

7-6 军事体能成绩统计(升级版)(模拟)

某校的体能考试中,男女生共同的体能项目为800米,立定跳远。还有一项男生为俯卧撑,女生为仰卧起坐。当输入n名学生(不超过20名)的成绩时,输入信息包括姓名、学号、性别、800米成绩、立定跳远成绩和俯卧撑/仰卧起坐的成绩,(假定输入成绩都是正确的)。如果为男生,最后一项成绩为俯卧撑,如果为女生则为仰卧起坐成绩。请输出所有各科目(800米、立定跳远、俯卧撑、仰卧起坐)的平均成绩(整数)及需补考(单个科目成绩低于60分)学生的姓名、学号和性别。

输入格式:

第一行为学生数n
第二行开始为n个学生的姓名、学号、性别、成绩1、 成绩2 、成绩3

输出格式:

第一行为每个科目的平均成绩,以逗号分隔

第二行开始为需补考人员的姓名、学号和性别,以逗号分隔,每个学生信息占一行

姓名,学号,性别

输入样例:

6
Lili 2001 M 80 50 90
Jim 2002 F 70 70 90
Tom 2003 F 90 80 90
May 2004 F 80 50 60
Jary 2005 M 30 50 90
Xiao 2006 M 60 80 100

输出样例:

68,63,93,80
Lili,2001,M
May,2004,F
Jary,2005,M

思路:简单模拟题,这里可以利用结构体来写会比较简单,思路上比较清晰明了,当然用数组来写也可以,只不过在逻辑上可能稍有复杂

AC代码:

#include <bits/stdc++.h>

using namespace std;

typedef struct {
    string name;
    int num;
    char sex;
    int g1, g2, g3;
}Person;

int main()
{
    int i, j, k, n, count = 0;
    int avg_run = 0, avg_jump = 0, avg_push = 0, avg_sit = 0;
    cin >> n;
    vector<Person>nums(n);
    for (i = 0; i < n; i++) {
        cin >> nums[i].name >> nums[i].num >> nums[i].sex >> nums[i].g1 >> nums[i].g2 >> nums[i].g3;
        avg_run += nums[i].g1;
        avg_jump += nums[i].g2;
        if (nums[i].sex == 'M') {
            avg_push += nums[i].g3;
            count++;
        } else avg_sit += nums[i].g3;
    }
    avg_run /= n;
    avg_jump /= n;
    avg_push /= count;
    avg_sit /= (n - count);
    cout << avg_run << "," << avg_jump << "," << avg_push << "," << avg_sit << endl;
    for (i = 0; i < n; i++) {
        if (nums[i].g1 < 60 || nums[i].g2 < 60 || nums[i].g3 < 60)
                cout << nums[i].name << "," << nums[i].num << "," << nums[i].sex << endl;
    }

    system("pause");
    return 0;
}

7-7 铺草坪提高版(思维)

有一块长为n宽为2的方形草坪,现用长为2宽为1的方形草皮将其铺满,请计算共有多少种不同的铺法?

输入格式:

输入只有一个正整数n(1=<n<=90),代表草皮的长度。

输出格式:

输出不同铺法的个数。

输入样例:

3

输出样例:

3

思路:这道题可以在大脑中或者纸上把前几种情况都枚举出来,枚举出的结果即为当n为1、2、3、4、5......的时候,不同的铺法分别为1、2、3、5、8......,这就不难看出这与斐波那契数列比较相似,从第三项就开始遵循Fn = Fn - 1 + Fn - 2,这里需要注意一点斐波那契数列增长速度可能会很快,用int型变量进行定义可能会造成溢出,所以要用longlong类型

AC代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

vector<ll>nums(100, 0);

int main()
{
    int i, j, k, n;
    nums[1] = 1, nums[2] = 2;
    for (i = 3; i < 100; i++) nums[i] = nums[i - 1] + nums[i - 2];

    cin >> n;
    cout << nums[n] << endl;


    system("pause");
    return 0;
}

7-8 FJCC-GPLT(模拟)

第114514届FujianJimeiComputerCompetition——Group ProgrammingLnddrTournament(FJCC−GPLT)正式拉开序幕,绝绝子!

主办单位:JMU_ACM

本次大赛的规则如下:

  1. 每支参赛队由 10名队员组成。

  2. 竞赛题目分3 个梯级:

    • 基础级(L1)设8 道题,其中 5分、10 分、15分、20分的题从前往后的顺序各 2 道,满分为100分;
    • 进阶级(L2)设 4道题,每道题25分,满分为 100分;
    • 登顶级(L3)设3道题,每道题30分,满分为90分。
  3. 参赛队员可以在比赛中的任何时刻尝试解决任何梯级的题目。但只有当一支队伍的基础题总分超过 800分时,其本队进阶部分的题目分数才被判为有效否则本队的进阶部分有效分数为0分。只有当其进阶题有效总分超过400分时,其本队登顶部分的题目分数才被判为有效。

  4. 禁止使用虚拟机。

  5. 禁止使用双屏,无论第二屏幕是否开启。

  6. 禁止佩戴耳机等电子设备。

  7. 比赛过程中禁止触碰 USB 接口。

  8. 除通过 OMS 客户端访问比赛指定题目集外,禁止以任何形式访问任何网站。

  9. 禁止使用任何形式的即时通信工具。

  10. 禁止打开任何事先存储在机器上的电子资料以及任何纸质资料。

  11. 禁止与监考老师以外的任何人交谈。

  12. 禁止拒绝监考老师的检查要求。严禁在检查过程中擅自关闭摄像头、监考客户端。

现在,作为主办方的leader——贝神想要知道目前的队伍排名,作为打下手的你,必须火速根据场上每队每个人的得分,给出每个队伍的排名。

输入格式:

输入第一行包括一个正整数n(n≤10)表示总共队伍数

接下来n×11行依次输入n个队伍的信息,每个队伍的信息如下:

最开始输入一行非空字符串(仅由英文字母和空格构成)表示队伍的名字,保证队伍名字不重复

随后10行,表示每个队员的得分,每行15个用空格隔开的非负整数,从左到右依次代表队员的L1−1L1−2...L1−8L2−1...L2−4L3−1...L3−3的成绩。(题目保证给出的得分合法,即小于等于该题的最大分值)

输出格式:

按照每个队伍的分数从高到低输出每个队伍的名字与分数(用空格隔开),如果有分数相同,则按照字典序小的优先。

tips:字典序是指从前到后比较两个字符串大小的方法。首先比较第1个字符,如果不同则第1个字符较小的字符串更小,如果相同则继续比较第二个字符,一直这样子比较下去。(字符为空则最小)

输入样例:

3
Can be trusted again
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
We can not repair computers
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
We can repair computers
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30
5 5 10 10 15 15 20 20 25 25 25 25 30 30 30

输出样例:

We can not repair computers 2900
We can repair computers 2900
Can be trusted again 360

思路:这道题的题干有点长,但抓住关键点会发现本题并不难,具体思路详见代码段

AC代码:

#include <bits/stdc++.h>

using namespace std;

vector<pair<string, int>>res;

void solve() {
    int i, j, k, n;
    int cnt1 = 0, cnt2 = 0, cnt3 = 0;
    string s;
    vector<vector<int>>nums(10, vector<int>(15, 0));
    getchar();
    getline(cin, s);
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 15; j++) {
            cin >> nums[i][j];
        }
    }
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 8; j++) cnt1 += nums[i][j];
        for (j = 8; j < 12; j++) cnt2 += nums[i][j];
        for (j = 12; j < 15; j++) cnt3 += nums[i][j];
    }
    int ans = 0;
    if (cnt1 > 800) {
        if (cnt2 > 400) ans += cnt2 + cnt3 + cnt1;
        else ans += cnt2 + cnt1;
    } else ans += cnt1;
    
    res.push_back({s, ans});
}

int main()
{
    int i, n;
    cin >> n;
    while (n--) {
        solve();
    }

    sort(res.begin(), res.end(), [](pair<string, int> &a, pair<string, int> &b) {
        if (a.second == b.second) return a.first < b.first;
        else return a.second > b.second;
    });

    for (i = 0; i < res.size(); i++) {
        cout << res[i].first << " " << res[i].second << endl;
    }

    system("pause");
    return 0;
}

7-9 看照片找基友(并查集)

 小A是个单身狗,他有很多好基友,他们平时喜欢出去聚会和旅游,每次聚会都会照一张集体照上传到群共享,有一天,小A整理照片,想通过照片来看看他们这群基友的情况。我们假定,在同一张照片里同时出现的,两两之间都是好基友,基友的基友也是好基友。那么问题来了,你能帮小A确定任意的两个人是否好基友吗?

输入格式:

首先输入照片的张数N(N<10000),之后N行,按以下格式输入照片里的情况:

K P1 P2 P3 …… PK

其中K是照片中的人数,后面的K个数是照片中人的编号,我们假定从1开始连续编号,人数不超过10000。
接下来输出查询的个数T(T<10000),之后T行,每行输入两个数,分别是查询的两个人的编号。

输出格式:

首先输出基友圈的个数和所有人数,之后对T组查询,在一行中输出查询结果,如果两个是好基友,输出Yes,否则输出No。

输入样例:

在这里给出一组输入。例如:

4
3 11 1 2
3 3 4 10
4 1 5 7 8
3 9 6 12
2
10 5
7 11

输出样例:

在这里给出相应的输出。例如:

3 12
No
Yes

思路:并查集板子题,这里需要注意一点题干所说“后面K个数是照片中的编号”,总人数不超过10000,但是照片中人的编号可能超过1000,还有一点就是输入的情况可能会出现编号为1,2,3,4,6.因为出现的最大编号为6,即便没出现编号5,那么接下来我们查询的人中也可能出现5,这一个测试点有两个坑点,如果思路没问题没拿满分的话可能是这个点没考虑

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 10010;

vector<int>fa(MAXN, 0);

void init() {
    for (int i = 0; i < MAXN; i++) {
        fa[i] = i;
    }
}

int find(int x) {
    if (fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}

void unionset(int a, int b) {
    int x = find(a), y = find(b);
    if (x != y) fa[y] = x;
}

int main()
{
    init();
    set<int>st;
    int i, j, k, n, size = 0;
    cin >> n;
    while (n--) {
        int x;
        cin >> x;
        vector<int>v(x, 0);
        for (i = 0; i < x; i++) {
            cin >> v[i];
            size = max(min(10000, v[i]), size);
        }
        for (i = 1; i < x; i++) unionset(v[0], v[i]);
    }

    int count = 0;
    for (i = 1; i <= size; i++) if (fa[i] == i) count++;
    cout << count << " " << size << endl;

    int t;
    cin >> t;
    while (t--) {
        int a, b;
        cin >> a >> b;
        if (find(a) == find(b)) cout << "Yes" << endl;
        else cout << "No" << endl;
    }

    system("pause");
    return 0;
}

7-10 小猫爬山(dfs+剪枝)

Freda 和 Rainbow 饲养了 N 只小猫,这天,小猫们要去爬山。经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了。

Freda 和 Rainbow 只好花钱让它们坐索道下山。索道上的缆车最大承重量为 W,而 N 只小猫的重量分别是 C1​、C2​ …… CN​。当然,每辆缆车上的小猫的重量之和不能超过 W。每租用一辆缆车,Freda 和 Rainbow 就要付 1 元,所以他们想知道,最少需要付多少元才能把这 N 只小猫都运送下山?。

输入格式:

输入文件共 1+N 行。每行中两个数之间用一个空格隔开。

第一行包含两个用空格隔开的整数,N 和 W。

接下来 N 行每行一个整数,其中第 i+1 行的整数表示第 i 只小猫的重量 Ci​。

输出格式:

输出共 1 行,输出一个整数,最少需要多少元,也就是最少需要多少辆缆车。

输入样例:

5 1996
1
2
1994
12
29

输出样例:

2

输入输出样例解释:

第三只小猫(重量为 1994 )和第一只小猫(重量为 1 )坐一辆缆车,剩下的小猫坐一辆缆车,共两辆。

数据规模与约定:

对于 100% 的数据,1≤N≤18,1≤Ci​≤W≤108。

思路:本题我最开始想的使用贪心来写,但到后面发现有一个测试点过不了,看数据规模比较小,可以直接进行dfs搜索,这里需要注意剪枝,否则会造成超时,两个优化的点,一个是当你目前所需缆车的数量大于目前搜索到的最小值的话可以直接放弃这个枝干的搜索,因为小车的数量只能增长而不会减少,第二个则是尽量先将最胖的猫进行安置,因为体重较大猫比体重较小猫选择缆车的机会要少,dfs生成的层数会减少,同时能加快搜索的速度

最后这里补一下贪心过不了的点:

6 16

9 5 5 5 4 3

贪心的结果是使用 3 辆车,分别为9 + 5、5 + 5 + 4、3;而正确的结果却是使用 2 辆车,分别为9 + 4 + 3、5 + 5 + 5

AC代码:

#include <bits/stdc++.h>

using namespace std;

vector<int>nums, res;

int ans = INT_MAX;
int n, w;

void dfs(int index, int cnt) {
    if (cnt > ans) return;    
    if (index == n) {
        ans = min(ans, cnt);
        return;
    }

    for (int i = 0; i < cnt; i++) {
        if (res[i] - nums[index] >= 0) {
            res[i] -= nums[index];
            dfs(index + 1, cnt);
            res[i] += nums[index];
        }
    }

    res[cnt] -= nums[index];
    dfs(index + 1, cnt + 1);
    res[cnt] += nums[index];
}

int main()
{
    int i, j, k;
    cin >> n >> w;
    nums.resize(n, 0);
    res.resize(n, w);
    for (i = 0; i < n; i++) cin >> nums[i];
    sort(nums.begin(), nums.end(), greater<int>());
    dfs(0, 1);
    cout << ans << endl;

    system("pause");
    return 0;
}

7-11 h0075. 射击游戏(dfs)

在一个二维平面上有n个敌人,第i个敌人可以描述为一个以(xi,yi)为圆心,ri为半径的圆。

你每次可以对一个半径为R的圆范围内进行攻击(圆心自选,但圆心的横纵坐标必须为整数),对于与你攻击范围有交点的敌人都会被消灭。

你总共可以发动k次攻击,问最多能消灭多少敌人。

输入格式:

第一行以空格分隔的三个整数n,k,R。
接下来n行每行以空格分隔的三个整数xi ,yi ,ri 。
1≤n≤10
1≤k≤3
1≤ri ,R≤7
0≤xi,yi≤15
敌人的位置可能会有重叠。

输出格式:

输出一行一个正整数代表答案。

输入样例:

3 1 1
6 6 1
7 7 1
4 4 1

输出样例:

2

说明:

只能发动一次攻击,可以攻击圆心为(6,6)的圆,这样可以消灭第一个和第二个敌人。

思路:本题因为数据量比较少,所以可以用暴力搜索来写,这里注意一下判断条件是当两个圆相交的时候才会消灭敌人,判断相交的条件:圆心距≤半径和,可能有的同学会发现text2过不了,text2的数据可能有点问题(当然如果有人举出来了text2的样例欢迎评论或私聊指正),15分应该就是本题的满分

AC代码:

#include <bits/stdc++.h>

using namespace std;

vector<vector<int>>nums;
vector<bool>vis;

int ans = 0;
int n, k, R;

void dfs(int cnt, int res) {
    if (res == k) {
        ans = max(ans, cnt);
        return;
    }

    for (int i = 0; i <= 15; i++) {
        for (int j = 0; j <= 15; j++) {
            vector<int>v;
            for (int h = 0; h < n; h++) {
                if (vis[h]) continue;
                int d = (nums[h][0] - i) * (nums[h][0] - i) + (nums[h][1] - j) * (nums[h][1] - j);
                if (d <= (nums[h][2] + R) * (nums[h][2] + R)) {
                    v.push_back(h);
                    vis[h] = true;
                }
            }
            dfs (cnt + v.size(), res + 1);
            for (int h = 0; h < v.size(); h++) vis[v[h]] = false;
        }
    }
}

int main()
{
    int i, j, h;
    cin >> n >> k >> R;
    nums.resize(n, vector<int>(3, 0));
    vis.resize(n, false);

    for (i = 0; i < n; i++) cin >> nums[i][0] >> nums[i][1] >> nums[i][2];

    dfs(0, 0);

    cout << ans << endl;

    system("pause");
    return 0;
}

7-12 令人抓狂的四则运算(大模拟)

那么当我们学会使用计算机,自然是要程序去完成这个工作啦~ 现在请对输入的四则运算求值。注意:

  • 四则运算表达式必定包含运算数,还可能包含运算符和括号( )不含空格等其它字符
  • 运算数必定包含数字,还可能包含正或负符号+-以及小数点.
  • 运算符仅有+(加)、-(减)、*(乘以)、/(除以)四种
  • 括号可以嵌套
  • 对于带符号的数,可以加括号,也可以不加括号,例如:1+-2*+31+(-2)*(+3)是等价的
  • 括号内可以是包含运算符的表达式,也可以仅有运算数,例如:1*(2)1*(2+3)都是合法的表达式

输入格式:

输入由若干行组成:

  • 除最后一行之外,每一行是一个长度不超过80的四则运算表达式
  • 最后一行,是一个=字符

输入的所有字符均为英文半角字符,题目保证给定的表达式是正确的,不需要做有效性检查,题目保证所有运算数的长度(含小数点)均不超过5位,运算的中间结果和最终结果的绝对值均不超过100000

输出格式:

对输入的每个表达式,在一行中给出运算结果,保留1位小数。

输入样例:

1
1+2
3-3.8
1.32*(4+(-2))
=

输出样例:

1.0
3.0
-0.8
2.6

题解链接:

令人抓狂的四则运算_pta令人抓狂的四则运算-CSDN博客

7-13 寻宝图(BFS+连通块)

具体题解详见我之前的天梯赛题解的L2-4

2023年团体程序设计天梯赛(含部分题解)_清晨喝碗粥的博客-CSDN博客

7-14 完美树(树形DP,状态机,贪心)

给定一棵有 N 个结点的树(树中结点从 1 到 N 编号,根结点编号为 1)。每个结点有一种颜色,或为黑,或为白。

称以结点 u 为根的子树是 好的,若子树中黑色结点与白色结点的数量之差的绝对值不超过 1。称整棵树是 完美树,若对于所有 1 ≤ i ≤ N,以结点 i 为根的子树都是好的。

你需要将整棵树变成完美树,为此你可以进行以下操作任意次(包括零次):选择任意一个结点 i (1 ≤ i ≤ N),改变结点 i 的颜色(若结点 i 目前是黑色则将其改为白色,若结点 i 目前是白色则将其改为黑色)。这次操作的代价为 Pi​。

求将给定的树变为完美树的最小代价。

注:以结点 i 为根的子树,由结点 i 以及结点 i 的所有后代结点组成。

输入格式:

输入第一行为一个数 N (1≤N≤105),表示树的结点个数。

接下来的 N 行,第 i 行的前三个数为 Ci​,Pi​,Ki​ (1≤Pi​≤104,0≤Ki​≤N),分别表示树上编号为 i 的结点的初始颜色(0 为白色,1 为黑色)、变换颜色的代价及孩子结点的数量。紧跟着有 Ki​ 个数,为孩子结点的编号。数字均用一个空格隔开,所有的编号保证在 1 到 N 里,且不会有环。

数据中只包含一棵树。

输出格式:

输出一行一个数,表示将树 T 变为完美树的最小代价。

输入样例:

10
1 100 3 2 3 4
0 20 1 7
0 5 2 5 6
0 8 1 10
0 7 0
0 2 0
1 1 2 8 9
0 15 0
0 13 0
1 8 0

输出样例:

15

提示:

样例中最佳的方案是:将 9 号点和 6 号点从白色变为黑色,此时代价为 13 + 2 = 15。

详细讲解以及AC代码:

2023天梯赛L3-2 完美树-CSDN博客

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值