2024团体程序设计天梯赛L1-L2(196分)题解

目录

个人总结:

L1-1 编程解决一切(5分)

L1-2 再进去几个人(5分)

L1- 3 帮助色盲(10分)

L1- 4 四项全能(10分)

L1-4 别再来这么多猫娘了!(13分)

L1-5 兰州牛肉面(15分)

L1-6 整数的持续性(20分)

L1-7 九宫格(20分)

L2-1 鱼和熊掌(25分)

L2-2 懂蛇语(25分)

L2-3 满树的遍历(25分)

L2-4 吉利矩阵(23分)

我的代码只能拿196分,有些瑕疵请大佬们指出

个人总结:
最后130+,一开始发挥还行,后面陆陆续续断线搞心态,重连清空代码还,耽搁了一个小时左右,希望同学们下次一定要重视环境测试,别带有侥幸心理,也怪自己一开始侥幸心理用热点比赛吧。最终团队离银牌差一点点,希望下次加油吧。

L1-1 编程解决一切(5分)
编程解决一切 —— 本题非常简单,就请你直接在屏幕上输出这句话:“Problem? The Solution: Programming.”。

输入格式:

输出格式:
在一行中输出 Problem? The Solution: Programming.。

输入样例:

输出样例
Problem? The Solution: Programming.
AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
void solve(){
    cout<<"Problem? The Solution: Programming.";
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L1-2 再进去几个人(5分)
数学家、生物学家和物理学家坐在街头咖啡屋里,看着人们从街对面的一间房子走进走出。他们先看到两个人进去。时光流逝。他们又看到三个人出来。
物理学家:“测量不够准确。”
生物学家:“他们进行了繁殖。”
数学家:“如果现在再进去一个人,那房子就空了。”
下面就请你写个程序,根据进去和出来的人数,帮数学家算出来,再进去几个人,那房子就空了。

输入格式:
输入在一行中给出 2 个不超过 100 的正整数 A 和 B,其中 A 是进去的人数,B 是出来的人数。题目保证 B 比 A 要大。

输出格式:
在一行中输出使得房子变空的、需要再进去的人数。

输入样例:
4 7
输出样例:
3

解题方法:输出b-a就行

#include <bits/stdc++.h>
using namespace std;
int main(){
    int a,b;
    cin>>a>>b;
    cout<<b-a<<endl;
    return 0;
}

L1- 3 帮助色盲(10分)
在古老的红绿灯面前,红绿色盲患者无法分辨当前亮起的灯是红色还是绿色,有些聪明人通过路口的策略是这样的:当红灯或绿灯亮起时,灯的颜色无法判断,但前方两米内有同向行走的人,就跟着前面那人行动,人家走就跟着走,人家停就跟着停;如果当前是黄灯,那么很快就要变成红灯了,于是应该停下来。麻烦的是,当灯的颜色无法判断时,前方两米内没有人……
本题就请你写一个程序,通过产生不同的提示音来帮助红绿色盲患者判断当前交通灯的颜色;但当患者可以自行判断的时候(例如黄灯或者前方两米内有人),就不做多余的打扰。具体要求的功能为:当前交通灯为红灯或绿灯时,检测其前方两米内是否有同向行走的人 —— 如果有,则患者自己可以判断,程序就不做提示;如果没有,则根据灯的颜色给出不同的提示音。黄灯也不需要给出提示。

输入格式:
输入在一行中给出两个数字 A 和 B,其间以空格分隔。其中 A 是当前交通灯的颜色,取值为 0 表示红灯、1 表示绿灯、2 表示黄灯;B 是前方行人的状态,取值为 0 表示前方两米内没有同向行走的人、1 表示有。

输出格式:
根据输入的状态在第一行中输出提示音:dudu 表示前方为绿灯,可以继续前进;biii 表示前方为红灯,应该止步;- 表示不做提示。在第二行输出患者应该执行的动作:move 表示继续前进、stop 表示止步。

输入样例 1:
0 0
输出样例 1:
biii
stop
输入样例 2:
1 1

方法:黄灯或者有人输出-,其余状况看红灯还是绿灯
红黄stop 绿灯move

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
void solve(){
    int a,b;
    cin>>a>>b;

    if(a==2 || b==1)cout<<"-\n";
    else if(a==1)cout<<"dudu\n";
    else cout<<"biii\n";

    if(a==0 || a==2)cout<<"stop";
    else cout<<"move";
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L1- 4 四项全能(10分)
新浪微博上有一个帖子给出了一道题:全班有 50 人,有 30 人会游泳,有 35 人会篮球,有 42 人会唱歌,有 46 人会骑车,至少有( )人四项都会。
发帖人不会做这道题,但是回帖有会做的:每一个才艺是一个技能点,一共是 30 + 35 + 42 + 46 = 153 个技能点,50 个人假设平均分配,每人都会 3 个技能那也只有 150,所以至少有 3 人会四个技能。
本题就请你写个程序来自动解决这类问题:给定全班总人数为 n,其中有 m 项技能,分别有 k1​、k2​、……、km​ 个人会,问至少有多少人 m 项都会。

输入格式:
输入在第一行中给出 2 个正整数:n(4≤n≤1000)和 m(1<m≤n/2),分别对应全班人数和技能总数。随后一行给出 m 个不超过 n 的正整数,其中第 i 个整数对应会第 i 项技能的人数。

输出格式:
输出至少有多少人 m 项都会。

输入样例:
50 4
30 35 42 46
输出样例:
3

方法:技能点总和减去班级人数乘以m-1即可,如果小于0就取0(毕竟人数不可能是负数)
代码:(10分)

#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N=1e5+5;
void solve(){
    int n,m,total=0;
    cin>>n>>m;

    for(int i=1;i<=m;i++){
        int temp;
        cin>>temp;
        total+=temp;
    }
    
    cout<<max(0,total-(n*(m-1)));
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L1-5 别再来这么多猫娘了!(15分)
以 GPT 技术为核心的人工智能系统出现后迅速引领了行业的变革,不仅用于大量的语言工作(如邮件编写或文章生成等工作),还被应用在一些较特殊的领域——例如去年就有同学尝试使用 ChatGPT 作弊并被当场逮捕(全校被取消成绩)。相信聪明的你一定不会犯一样的错误!

言归正传,对于 GPT 类的 AI,一个使用方式受到不少年轻用户的欢迎——将 AI 变成猫娘:

当然,由于训练数据里并不区分道德或伦理倾向,因此如果不加审查,AI 会生成大量的、不一定符合社会公序良俗的内容。尽管关于这个问题仍有争论,但至少在比赛中,我们还是期望 AI 能用于对人类更有帮助的方向上,少来一点猫娘。

因此你的工作是实现一个审查内容的代码,用于对 AI 生成的内容的初步审定。更具体地说,你会得到一段由大小写字母、数字、空格及 ASCII 码范围内的标点符号的文字,以及若干个违禁词以及警告阈值,你需要首先检查内容里有多少违禁词,如果少于阈值个,则简单地将违禁词替换为;如果大于等于阈值个,则直接输出一段警告并输出有几个违禁词。

输入格式:
输入第一行是一个正整数 N (1≤N≤100),表示违禁词的数量。接下来的 N 行,每行一个长度不超过 10 的、只包含大小写字母、数字及 ASCII 码范围内的标点符号的单词,表示应当屏蔽的违禁词。
然后的一行是一个非负整数 k (0≤k≤100),表示违禁词的阈值。
最后是一行不超过 5000 个字符的字符串,表示需要检查的文字。
从左到右处理文本,违禁词则按照输入顺序依次处理;对于有重叠的情况,无论计数还是替换,查找完成后从违禁词末尾继续处理。

输出格式:
如果违禁词数量小于阈值,则输出替换后的文本;否则先输出一行一个数字,表示违禁词的数量,然后输出He Xie Ni Quan Jia!。

输入样例1:
5
MaoNiang
SeQing
BaoLi
WeiGui
BuHeShi
4
BianCheng MaoNiang ba! WeiGui De Hua Ye Keyi Shuo! BuYao BaoLi NeiRong.

输出样例1:
BianCheng ba! De Hua Ye Keyi Shuo! BuYao NeiRong.
输入样例2:
5
MaoNiang
SeQing
BaoLi
WeiGui
BuHeShi
3
BianCheng MaoNiang ba! WeiGui De Hua Ye Keyi Shuo! BuYao BaoLi NeiRong.

输出样例2:
3
He Xie Ni Quan Jia!
输入样例3:
2
AA
BB
3
AAABBB

方法:模拟题,模拟题意即可,那句重叠我真不理解什么意思,这题拿了13分,应该剩下两分就是这个问题。语文不好没办法,我在比赛用的Python,因为用py嘎嘎快
代码(13分)

n=int(input())
a=[]
for i in range(n):
    s=input()
    a.append(s)
m=int(input())
num=0
s=input()
for i in a:
    num+=s.count(i)
    s=s.replace(i,"<censored>")
if num<m:
    print(s)
else:
    print(num)
    print("He Xie Ni Quan Jia!")

L1-6 兰州牛肉面(15分)
兰州牛肉面是历史悠久的美食,根据牛肉面的宽窄、配料的种类,可以细分为上百个不同的品种。你进到兰州的任何一家牛肉面馆,只说:“来一碗牛肉面!”就好像进到加州的咖啡馆说“来一杯咖啡”一样,会被店主人当成外星人……
本题的任务是,请你写程序帮助一家牛肉面馆的老板统计一下,他们一天卖出各种品种的牛肉面有多少碗,营业额一共有多少。

输入格式:
输入第一行给出一个正整数 N(≤100),为牛肉面的种类数量。这里为了简单起见,我们把不同种类的牛肉面从 1 到 N 编号,以后就用编号代替牛肉面品种的名称。第二行给出 N 个价格,第 i 个价格对应第 i 种牛肉面一碗的单价。这里的价格是 [0.01, 200.00] 区间内的实数,以元为单位,精确到分。
随后是一天内客人买面的记录,每条记录占一行,格式为:

品种编号 碗数
其中碗数保证是正整数。当对应的 品种编号 为 0 时,表示输入结束。这个记录不算在内。

输出格式:
首先输出 N 行,第 i 行输出第 i 种牛肉面卖出了多少碗。最后一行输出当天的总营业额,仍然是以元为单位,精确到分。题目保证总营业额不超过 106。

方法:一个数组存储碗数,一个数组存储价格,总消费额累加就行

输入样例:
5
4.00 8.50 3.20 12.00 14.10
3 5
5 2
1 1
2 3
2 2
1 9
0 0
输出样例:
10
5
5
0
2
126.70

#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N=1e5+5;
double price[N];//价格
int num[N];//碗数
void solve(){
    int n,a,b;
    double ans=0;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>price[i];
    }
    while(cin>>a>>b){
        if(a==0)break;
        num[a]+=b;
        ans+=price[a]*b;
    }
    for(int i=1;i<=n;i++){
        printf("%d\n",num[i]);
    }
    printf("%.2lf",ans);
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L1-7 整数的持续性(20分)
从任一给定的正整数 n 出发,将其每一位数字相乘,记得到的乘积为 n1​。以此类推,令 ni+1​ 为 ni​ 的各位数字的乘积,直到最后得到一个个位数 nm​,则 m 就称为 n 的持续性。例如 679 的持续性就是 5,因为我们从 679 开始,得到 6×7×9=378,随后得到 3×7×8=168、1×6×8=48、4×8=32,最后得到 3×2=6,一共用了 5 步。
本题就请你编写程序,找出任一给定区间内持续性最长的整数。

输入格式:
输入在一行中给出两个正整数 a 和 b(1≤a≤b≤109 且 (b−a)<103),为给定区间的两个端点。

输出格式:
首先在第一行输出区间 [a,b] 内整数最长的持续性。随后在第二行中输出持续性最长的整数。如果这样的整数不唯一,则按照递增序输出,数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:
500 700
输出样例:
5
679 688 697

方法:存储每个持续性的整数合集,只需用一个返回数字持续性的函数,把区间内的数字分到他们该去的地方就好,比如持续性为5的数字都应该进入到num[5]里

代码(20分):

#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define endl '\n'
const int N=1e5+5;
vector<int> res[N];
int find(int num){
    //返回一个数的每位乘积
    int ans=1;
    while(num){
        ans*=num%10;
        num/=10;
    }
    return ans;
}
int check(int num){
    //返回一个数的持续性
    int ans=0;
    while(num>=10){
        ans++;
        num=find(num);
    }
    return ans;
}
void solve(){
    int a,b,maxnum=-1;
    cin>>a>>b;

    for(int i=a;i<=b;i++){
        int temp=check(i);
        res[temp].push_back(i);
        maxnum=max(maxnum,temp);
    }
    cout<<maxnum<<endl;
    for(int i=0;i<res[maxnum].size();i++){
        if(i<res[maxnum].size()-1)cout<<res[maxnum][i]<<" ";
        else cout<<res[maxnum][i];
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L1-8 九宫格(20分)
九宫格是一款数字游戏,传说起源于河图洛书,现代数学中称之为三阶幻方。游戏规则是:将一个 9×9 的正方形区域划分为 9 个 3×3 的正方形宫位,要求 1 到 9 这九个数字中的每个数字在每一行、每一列、每个宫位中都只能出现一次。
本题并不要求你写程序解决这个问题,只是对每个填好数字的九宫格,判断其是否满足游戏规则的要求。

输入格式:
输入首先在第一行给出一个正整数 n(≤10),随后给出 n 个填好数字的九宫格。每个九宫格分 9 行给出,每行给出 9 个数字,其间以空格分隔。

输出格式:
对每个给定的九宫格,判断其中的数字是否满足游戏规则的要求。满足则在一行中输出 1,否则输出 0。

输入样例:
3
5 1 9 2 8 3 4 6 7
7 2 8 9 6 4 3 5 1
3 4 6 5 7 1 9 2 8
8 9 2 1 4 5 7 3 6
4 7 3 6 2 8 1 9 5
6 5 1 7 3 9 2 8 4
9 3 4 8 1 6 5 7 2
1 6 7 3 5 2 8 4 9
2 8 5 4 9 7 6 1 3
8 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 3
81 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 2

输出样例:
1
0
0

方法:模拟即可(比赛的时候少看了每行每列的要求一直一个测试点没过)
模拟题基本都不难,看清题意最重要

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+5;
int g[105][105];
bool check(int x,int y){
    bool st[10]={0};
    for(int i=x;i<=x+2;i++){
        for(int j=y;j<=y+2;j++){
            if(g[i][j]<1 || g[i][j]>9)continue;
            st[g[i][j]]=1;
        }
    }
    for(int i=1;i<=9;i++){
        if(st[i]!=1)return 0;
    }
    return 1;
}
void solve(){
    bool f=1;
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            cin>>g[i][j];
        }
    }
    for(int i=1;i<=9;i++){
        for(int x=1;x<=9;x+=3){
            for(int y=1;y<=9;y+=3){
                if(!check(x,y))f=0;
            }
        }
    }
    for(int i=1;i<=9;i++){
        bool st[10]={0};
        for(int j=1;j<=9;j++){
            if(g[i][j]<1 || g[i][j]>9)continue;
            st[g[i][j]]=1;
        }
        for(int i=1;i<=9;i++){
             if(st[i]!=1)f=0;
        }
    }
    for(int i=1;i<=9;i++){
        bool st[10]={0};
        for(int j=1;j<=9;j++){
            if(g[j][i]<1 || g[j][i]>9)continue;
            st[g[j][i]]=1;
        }
        for(int i=1;i<=9;i++){
             if(st[i]!=1)f=0;
        }
    }
    
    cout<<f<<endl;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

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

L2-1 鱼和熊掌(25分)
孟子 · 告子上》有名言:“鱼,我所欲也,熊掌,亦我所欲也;二者不可得兼,舍鱼而取熊掌者也。”但这世界上还是有一些人可以做到鱼与熊掌兼得的。
给定 n 个人对 m 种物品的拥有关系。对其中任意一对物品种类(例如“鱼与熊掌”),请你统计有多少人能够兼得?

输入格式:
输入首先在第一行给出 2 个正整数,分别是:n(≤105)为总人数(所有人从 1 到 n 编号)、m(2≤m≤105)为物品种类的总数(所有物品种类从 1 到 m 编号)。
随后 n 行,第 i 行(1≤i≤n)给出编号为 i 的人所拥有的物品种类清单,格式为:

K M[1] M[2] … M[K]
其中 K(≤103)是该人拥有的物品种类数量,后面的 M[*] 是物品种类的编号。题目保证每个人的物品种类清单中都没有重复给出的种类。
最后是查询信息:首先在一行中给出查询总量 Q(≤100),随后 Q 行,每行给出一对物品种类编号,其间以空格分隔。题目保证物品种类编号都是合法存在的。

输出格式:
对每一次查询,在一行中输出两种物品兼得的人数。

输入样例:
4 8
3 4 1 8
4 7 1 8 4
5 6 5 1 2 3
4 3 2 4 8
3
2 3
7 6
8 4
输出样例:
2
0
3

方法:
我们首先分析一下数据量,n和m都是1e5,emmm有点吓人,但是这个q只有1e2,所以我们猜测,每次询问执行的函数的复杂度应该在1e5左右。题目要求两个物品都有的人数,我们以每个物品为门牌号,创建一个数组,一号物品对应数组1,里面存着所有拥有1物品人的编号。然后每次询问,我们遍历两个物品的数组,如果其中有序号等于2,说明这个人两个都有,答案+1,复杂度为1e5左右,是可行的。

代码(25分):

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+5;
int n,m;
vector<int> a[N];

//a[i]是一个数组,存储着所有拥有i物品的人的编号
int find(int n1,int n2){
    //返回同时拥有n1和n2的人数
    //时间复杂度为o(n)
    int num[N]={0},ans=0;//代表拥有这件物品的人数
    for(int i=0;i<a[n1].size();i++)num[a[n1][i]]++;
    for(int i=0;i<a[n2].size();i++)num[a[n2][i]]++;
    for(int i=1;i<=n;i++){
        if(num[i]==2)ans++;
    }
    return ans;
}
void solve(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int t;
        cin>>t;
        for(int j=1;j<=t;j++){
            int hao;
            cin>>hao;
            a[hao].push_back(i);
        }
    }
    int q;
    cin>>q;
    while(q--){
        int l,r;
        cin>>l>>r;
        cout<<find(l,r)<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L2-2 懂蛇语(25分)
在《一年一度喜剧大赛》第二季中有一部作品叫《警察和我之蛇我其谁》,其中“毒蛇帮”内部用了一种加密语言,称为“蛇语”。蛇语的规则是,在说一句话 A 时,首先提取 A 的每个字的首字母,然后把整句话替换为另一句话 B,B 中每个字的首字母与 A 中提取出的字母依次相同。例如二当家说“九点下班哈”,对应首字母缩写是 JDXBH,他们解释为实际想说的是“京东新百货”……
本题就请你写一个蛇语的自动翻译工具,将输入的蛇语转换为实际要表达的句子。

输入格式:
输入第一行给出一个正整数 N(≤105),为蛇语词典中句子的个数。随后 N 行,每行用汉语拼音给出一句话。每句话由小写英文字母和空格组成,每个字的拼音由不超过 6 个小写英文字母组成,两个字的拼音之间用空格分隔。题目保证每句话总长度不超过 50 个字符,用回车结尾。注意:回车不算句中字符。
随后在一行中给出一个正整数 M(≤103),为查询次数。后面跟 M 行,每行用汉语拼音给出需要查询的一句话,格式同上。

输出格式:
对每一句查询,在一行中输出其对应的句子。如果句子不唯一,则按整句的字母序输出,句子间用 | 分隔。如果查不到,则将输入的句子原样输出。
注意:输出句子时,必须保持句中所有字符不变,包括空格。

输入样例:
8
yong yuan de shen
yong yuan de she
jing dong xin bai huo
she yu wo ye hui shuo yi dian dian
liang wei bu yao chong dong
yi dian dian
ni hui shuo she yu a
yong yuan de sha
7
jiu dian xia ban ha
shao ye wu ya he shui you dian duo
liu wan bu yao ci dao
ni hai shi su yan a
yao diao deng
sha ye ting bu jian
y y d s

输出样例:
jing dong xin bai huo
she yu wo ye hui shuo yi dian dian
liang wei bu yao chong dong
ni hui shuo she yu a
yi dian dian
sha ye ting bu jian
yong yuan de sha|yong yuan de she|yong yuan de shen

方法:模拟题,只需将蛇语字典的每个缩写建立一个哈希表,映射到一个存储字符串的数组,然后在输出的时候先排序再输出即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+5;
int n,m;
map<string,vector<string>> mp;
string find(string s){
    //返回字符串的缩写
    int pos = 0;
    string res;
    // 判断字符串开头有没有空格
    if (s[pos] != ' '){
        res.push_back(s[0]);
    }
    //查找每个空字符后的有效首字符
    for(int i=1;i<s.size();i++){
        if(s[i-1]==' '&& s[i] !=' ')res+=s[i];
    }
    return res;
}
void out(string s,string old){
    if(mp[s].size()){
        sort(mp[s].begin(),mp[s].end());
        cout<<mp[s][0];
        for(int i=1;i<mp[s].size();i++)
            cout<<"|"<<mp[s][i];
        cout<<endl;
    }
    else cout<<old<<endl;
}
void solve(){
    cin>>n;
    string temp;
    for(int i=1;i<=n+1;i++){
        getline(cin,temp);
        if(temp=="")continue;
        //cout<<temp<<endl;
        string mo=find(temp);
        mp[mo].push_back(temp);
    }
    cin>>m;
    for(int i=1;i<=m+1;i++){
        getline(cin,temp);
        if(temp=="")continue;
        string mo=find(temp);
        out(mo,temp);
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L2-3 满树的遍历(25分)
一棵“k 阶满树”是指树中所有非叶结点的度都是 k 的树。给定一棵树,你需要判断其是否为 k 阶满树,并输出其前序遍历序列。

注:树中结点的度是其拥有的子树的个数,而树的度是树内各结点的度的最大值。

输入格式:
输入首先在第一行给出一个正整数 n(≤105),是树中结点的个数。于是设所有结点从 1 到 n 编号。
随后 n 行,第 i 行(1≤i≤n)给出第 i 个结点的父结点编号。根结点没有父结点,则对应的父结点编号为 0。题目保证给出的是一棵合法多叉树,只有唯一根结点。

输出格式:
首先在一行中输出该树的度。如果输入的树是 k 阶满树,则加 1 个空格后输出 yes,否则输出 no。最后在第二行输出该树的前序遍历序列,数字间以 1 个空格分隔,行首尾不得有多余空格。
注意:兄弟结点按编号升序访问。

输入样例 1:
7
6
5
5
6
6
0
5
输出样例 1:
3 yes
6 1 4 5 2 3 7
输入样例 2:
7
6
5
5
6
6
0
4
输出样例 2:
3 no
6 1 4 7 5 2 3

方法:我的方法用邻接表存储图,然后度的话也就是结点的子节点数目的最大值,如果是k阶满树,则所有子节点数非0的结点必须保持一致。然后递归前序遍历即可(最后一个不允许有空格也太无语了。。。。,我还得遍历去找最后一个叶子结点)

代码(25分)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+5;
int n;
vector<int> son[N];
int num[N],ed=-1;//num[i]代表i的度
//邻接表存储树

void dfs(int x){
    ed=x;
    for(int i=0;i<son[x].size();i++){
        dfs(son[x][i]);
    }
}
void dfs2(int x){
    //输出
    if(x!=ed)
        cout<<x<<" ";
    else 
        cout<<x;
    for(int i=0;i<son[x].size();i++){
        dfs2(son[x][i]);
    }
}
void solve(){
    int root=-1,du=-1;
    cin>>n;
    for(int i=1;i<=n;i++){
        int temp;
        cin>>temp;
        son[temp].push_back(i);
        num[temp]++;//temp是父节点,多一个子节点代表子树增加
        if(temp==0)root=i;
    }
    for(int i=1;i<=n;i++){
        sort(son[i].begin(),son[i].end());
        du=max(du,num[i]);
    }
    bool f=1;
    for(int i=2;i<=n;i++){
        if(num[i]!=du && num[i]!=0)f=0;
    }//判断所有非叶子结点的度是否相同

    cout<<du;
    if(f)cout<<" yes\n";
    else cout<<" no\n";
    dfs(root);//找最后 因为末尾不能有空格(无语)
    dfs2(root);//输出
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

L2-4 吉利矩阵(25分)
所有元素为非负整数,且各行各列的元素和都等于 7 的 3×3 方阵称为“吉利矩阵”,因为这样的矩阵一共有 666 种。
本题就请你统计一下,把 7 换成任何一个 [2,9] 区间内的正整数 L,把矩阵阶数换成任何一个 [2,4] 区间内的正整数 N,满足条件“所有元素为非负整数,且各行各列的元素和都等于 L”的 N×N 方阵一共有多少种?

输入格式:
输入在一行中给出 2 个正整数 L 和 N,意义如题面所述。数字间以空格分隔。

输出格式:
在一行中输出满足题目要求条件的方阵的个数。

输入样例:
7 3
输出样例:
666

方法:
dfs+剪枝,我们在搜索的时候,如果当前值已经大于目标值,应当停止搜索。然后回溯条件也要注意,我们要还原副本,防止对上层的影响。
代码只能过23分,有2分运行超时估计死循环了没调试出来。。
代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=1e5+5;
int a,b,ans=0;
int row[10],line[10],n,m;
void dfs(int x,int y){
    
    if(x>b || y>b){
        ans++;
        return;
    }
    if(line[x]>a || row[y]>a)return;//剪枝
    //当前值大于a,再搜下去没有意义
    
    for(int i=0;i<=a;i++){
        line[x]+=i;
        row[y]+=i;
        int f=0;
        if(x==b){
            if(row[y]==a)f++;
        }
        else
            f++;
        if(y==b){
            if(line[x]==a) f++;
        }
        else
            f++;
        if(f==2)
            dfs(x+(y/b),y%b+1);//搜索下一个位置
        
        line[x]-=i;
        row[y]-=i;
}
}
void solve(){
    cin>>a>>b;
    dfs(1,1);
    cout<<ans;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
}

个人反思:还是自己的原因,带有侥幸心理,一开始就调试好设备的话就不会有这么多问题。也害团队失去了银牌,后面断线重连花了好多时间,越搞越慌,最主要的是每次重连都会清空代码。。。。希望考研加油吧呜呜呜。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值