• xxx
  • 2025花都区少年宫信息赛编程题部分

  • @ 2025-5-30 20:54:00

各位参赛选手家长、指导老师:

大家好!经过严格评审,软件编程赛项线下决赛名单已确定,现将相关事宜通知如下:

一、决赛名单公布 本次公布的名单为软件编程赛项线下决赛入围名单,成功入选的选手请认真备赛。

二、奖项说明 所有比赛成绩(奖项)将于下周内统一发布。未入选决赛的选手,不代表未获奖,最终结果请耐心等待统一公布 。

三、决赛联系事宜 线下决赛将于6月1日在花都区青少年文化宫(市民广场宫)进行,请参加决赛选手的联系人或指导老师,尽快联系赛事黄烽晋老师沟通后续安排。

一、线下决赛时间: 6月1日暂定上午9:00-11:30,具体时间和课室安排等群上安排通知 二、决赛前准备内容: 各组别选手在编程题中三选一自行完成,并将该题目代码文件命名“姓名+赛项+组别”发送至邮箱1601523494@qq.com,请在5月31日中午12点前完成发送。 三、线下决赛内容: 根据选手发送的题目代码,评委将询问选手关于题目的解题思路等。

比赛题目点击这里查看和测试

题解查看下面评论区

3 条评论

  • @ 2025-5-31 0:39:37

    第三题:木材切割(二分查找)

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        int n,k;
        cin>>n>>k;
        int L[n];
        for(int i=0;i<n;i++){
            cin>>L[i];
        }//输入 
        int left=1,right=0;//left最小可能长度 
        for(int i=1;i<n;i++){
        	if(L[i]>right){
        		right=L[i]; 
    		} 
    	}//搜索right的最大值,也可以用*max_element(L,L+n) 
        int ans=0;//存储答案 
        while(left<=right) {
            int mid=left+(right-left)/2;//找中间值,防止溢出,从left开始,加上区间长度的一半
    		//left+(right-left)=left+right/2-left/2=(left+right)/2 
            long long sum=0;//存储mid时能切出的总段数 
            for(int i=0;i<n;i++) {
                sum+=L[i]/mid;//sum+=每根原木能切出的段数 
            }
            if(sum>=k) {
                ans=mid;
                left=mid+1;//如果能切更大的段数,向右搜索,尝试更大的数 
            }else{
                right=mid-1;//否则尝试更小的数,向左搜索 
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    ```
    `
    • @ 2025-5-30 21:56:41

      第二题:评选

      #include <iostream>
      #include <algorithm>
      using namespace std;
      struct stu
      {
      	string s;//干员名称
      	int d, f, g, ni;
      	//d:任务危险程度
      	//f:任务评分
      	//g:任务奖金
      	//ni:编号(资历)
      }a[200005];//储存n个人
      int n, glen, alen;//glen:“神”的数量   alen:非神的数量
      string g[100005];
      bool cmp(stu x, stu y)
      {
      	//如果危险程度不同,就按危险程度从大到小排序
      	if (x.d != y.d)return x.d > y.d;
      	//如果任务评分不同,就按评分从大到小排序
      	if (x.f != y.f)return x.f > y.f;
      	//如果奖金不同,就按奖金从大到小排序
      	if (x.g != y.g)return x.g > y.g;
      	//否则就按资历从小到大排序
      	return x.ni < y.ni;
      }
      int main()
      {
      	cin >> n;//有n个人
      	for (int i = 1; i <= n; i++)
      	{
      		//第i个人的数据
      		string ns;
      		int nd, nf, ng;
      		cin >> ns >> nd >> nf >> ng;
      		//封为“神”,存入g
      		if (nd > 200)
      		{
      			g[++glen] = ns;
      			continue;
      		}
      		//否则就是普通人
      		a[++alen] = {ns, nd, nf, ng, i};
      	}
      	//先输出“神”
      	for (int i = 1; i <= glen; i++)
      	{
      		cout << g[i] << "\n";
      	}
      	//排序
      	sort(a + 1, a + alen + 1, cmp);
      	//输出
      	for (int i = 1; i <= alen; i++)
      	{
      		cout << a[i].s << "\n";
      	}
      	return 0; 
      }
      
      • @ 2025-5-30 21:01:49

        第一题:体检

        这题就是普通的模拟题,也可以输入时候先用二维数组存储然后再统一处理求平均数,也可以在线形式边输入就直接处理输出结果无需存储数据。

        唯一要注意的是,输出结果有的是整数,有的要保留两位小数的实数

        #include <iostream>
        #include <iomanip>
        using namespace std;
        int n,m;
        int main(){
        	cin>>n>>m;
        	for(int i=1;i<=n;i++){//有n个人 
        		int x,s=0;
        		for(int j=1;j<=m;j++){//每个人进行m次体检 
        			cin>>x;//输入健康值 
        			s+=x;//健康值求和 
        		}
        		if(s%m==0) //如果能整除则输出整数 
        			cout<<s/m<<" ";
        		else//否则输出保留两位小数
        			cout<<fixed<<setprecision(2)<<1.0*s/m<<" ";//1.0*s的作用是将结果转为实数 
        	}
        	return 0;
        }
        

        第二题:评选

        这是一道结构体存储数据,然后根据排序规则排序的题目

        #include <bits/stdc++.h>
        using namespace std;
        struct stu{//定义员工结构体 
        	string s;
        	int d,f,g,id;
        }a[200005];
        string s;
        int n,n2,d,f,g;
        bool cmp(stu x,stu y){//sort比较规则函数 
        	return tie(x.d,x.f,x.g,y.id)>tie(y.d,y.f,y.g,x.id);
        }
        int main(){
        	cin>>n;
        	for(int i=1;i<=n;i++){
        		cin>>s>>d>>f>>g;
        		if(d>200){//如果危险程度超过200,神干员直接输出 
        			cout<<s<<endl;
        		}else{//否则存储员工信息到a[] 
        			n2++;//非神干员数 
        			a[n2].s=s;a[n2].d=d;a[n2].f=f;a[n2].g=g;a[n2].id=i;
        		}
        	}
        	sort(a+1,a+n2+1,cmp);//按规则排序 
        	for(int i=1;i<=n2;i++){
        		cout<<a[i].s<<endl;//输出剩余n2名干员的名称 
        	}
        	return 0;
        }
        

        cmp部分不熟悉tie或者tuple的,可用用以下代码替换:

        bool cmp(stu x,stu y){
        	if(x.d!=y.d)return x.d>y.d;
        	if(x.f!=y.f)return x.f>y.f;
        	if(x.g!=y.g)return x.g>y.g;
        	return x.id<y.id;
        }
        

        第三题:切割木材

        这是一题求最小值最大的二分答案题

        先假设题目的答案在[L,R)区间范围内,然后通过验证中间值m=(L+R)/2,是否可行,逐步对半缩小答案范围,直到最终[L,R)之间只有一个符合要求的数即为答案

        二分查找的写法按照区间设置的不同有三种写法,详情请点击查看关于二分法的三种写法分析

        #include <bits/stdc++.h>
        using namespace std;
        int n,k,a[1000005],l,r,m;
        bool check(int x){//判断按照x长度切割是否可行 
        	int cnt=0;
        	for(int i=1;i<=n;i++){
        		cnt+=a[i]/x;
        		if(cnt>=k)return true;//如果能达到k段,则可行 
        	}
        	return false;
        }
        int main(){
        	//二分答案,求最小值最大,采用左闭右开区间二分查找答案值 
        	cin>>n>>k;
        	for(int i=1;i<=n;i++){
        		cin>>a[i];
        		r=max(r,a[i]);//答案的最大值无法超过a[i]的最大那根 
        	}
        	l=0;r++;//假设答案值在[1,r)之间所以r要比答案多1 
        	while(r-l>1){//采用左闭右开区间方式的二分答案查找
        		int m=(r-l)/2+l;//等价于=(r+l)/2,这样写防止r+l爆int范围
        		if(check(m)){//如果m符合切割要求 
        			l=m;//m可能是答案,缩小l 
        		}else{//否则m不符合切割要求 
        			r=m;//说明m不是答案,缩小r 
        		}
        	}
        	cout<<l;//如果l为0,则说明无自然数解 
        	return 0;
        }
        
        • 1