第七届传智杯全国IT技能大赛-程序设计赛道第一场院校赛(初赛)B组题解

目录

第一题,

第二题,

第三题,字符串

第四题,最优

第五题,模拟

第六题,二分


73854736868d47e99296659cbb50c6a0.png

第一题,吃糖果

排序贪心。贪心注意到先吃甜度之较小的糖果是最优的。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
int a[200010];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	int sum=0,res=0;
	for(int i=1;i<=n;i++){
		if(a[i]<=k){
			res++;
			k-=a[i];
		}else{
			break;
		}
	}
	cout<<res<<endl;
	return 0;
}

第二题,游游的重组偶数

数学知识 、分类讨论。注意到末尾为偶数即偶数,移动一个偶数到末尾即可。特别的,如果这样做会导致前导零,需要特判。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
int a[15];
void solve(){
	string s;cin>>s;
	int n = s.size();
	int t = s[n-1]-'0'; 
	if(t%2==0){
		cout<<s<<endl;
		return ;
	}
	int  num=-1;
	for(int i=0;i<n;i++){
		int tmp=s[i]-'0';
		if(tmp%2==0) {
			num=i; 
		}
	}
	if(num==-1){
		cout<<-1<<endl;
		return;
	}
	for(int i=0;i<n;i++){
		if(i!=num) cout<<s[i];
	}
	cout<<s[num]<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

第三题,开心还是难过

字符串暴力模拟。检查给定的字符串中是否存在emoji,由于范围较小。直接暴力即可,不需要使用字符串匹配算法,但是如果会用,也可以直接使用诸如find一类的内置函数。

#include <bits/stdc++.h>
using namespace std;
#define int long long  
void solve(){ 
	string s;
	getline(cin,s);
	cout<<s<<endl;
	int n=s.size();
	int l=0,r=0;
	if(n<3){
		cout<<"None"<<endl;
		return ;
	}
	for(int i=0;i<n-2;i++){
		if(s[i]==':'&& s[i+1]=='-'){
			if(s[i+2]=='(')l++;
			if(s[i+2]==')') r++;
		}
	}
	if(r==0&&l==0){
		cout<<"None"<<endl;
		return;
	}
	if(r>l) cout<<"Happy"<<endl;
	if(r==l) cout<<"Just so so"<<endl;
	if(r<l) cout<<"Sad"<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	//cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

第四题,小欧的平面连线

几何数学推导,我们需要对平面上的点进行配对,使得连线与坐标轴的交点尽可能多。关键在于理解线段与坐标轴相交的条件,以及如何通过巧妙的配对来最大化权值和。考虑从点的分布入手,第一三象限,第二四象限的点连接权值为2。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n' 
void solve(){ 
	int n;
	cin>>n;
	int num1=0,num2=0,num3=0,num4=0;
	for(int i=1;i<=n;i++){
		int x,y;
		cin>>x>>y;
		if(x>0&&y>0) num1++;
		else if(x<0&&y>0) num2++;
		else if(x<0&&y<0) num3++;
		else if(x>0&&y<0)num4++;
	} 
	int tmp1=min(num1,num3);
	int tmp2=min(num2,num4);
	int tmp=min(num1+num3-2*tmp1,num2+num4-2*tmp2); 
	int res = 2*tmp1 + 2*tmp2 + tmp; 
	cout<<res<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	//cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

第五题,小红的四子棋

模拟搜索 。对于每一个位置检查其是否位于一个合法的连珠序列上即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n' 
char s[110][110];
int n,m;
int fp1(char c,int i,int j){    // 横
	int num=1;
	for(int k=1;k<=7;k++){
		if(j+k>m) break;
		if(s[i][j+k]!=c) break;
		num++;
	}
	for(int k=1;k<=7;k++){
		if(j-k<1) break;
		if(s[i][j-k]!=c) break;
		num++;
	}
	return num;
}
int fp2(char c,int i,int j){    // 竖
	int num=1;
	for(int k=1;k<=7;k++){
		if(i+k>n) break;
		if(s[i+k][j]!=c) break;
		num++;
	}
	for(int k=1;k<=7;k++){
		if(i-k<1) break;
		if(s[i-k][j]!=c) break;
		num++;
	}
	return num;
}
int fp3(char c,int i,int j){    // 对角线 1
	int num=1;
	for(int k=1;k<=7;k++){
		if(i+k>n||j+k>m) break;
		if(s[i+k][j+k]!=c) break;
		num++;
	}
	for(int k=1;k<=7;k++){
		if(i-k<1||j-k<1) break;
		if(s[i-k][j-k]!=c) break;
		num++;
	}
	return num;
}
int fp4(char c,int i,int j){    // 对角线 2
	int num=1;
	for(int k=1;k<=7;k++){
		if(i-k<1||j+k>m) break;
		if(s[i-k][j+k]!=c) break;
		num++;
	}
	for(int k=1;k<=7;k++){
		if(i+k>n||j-k<1) break;
		if(s[i+k][j-k]!=c) break;
		num++;
	}
	return num;
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>s[i][j];
		}
	}
	int maxr=0,maxp=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int num1=0,num2=0,num3=0,num4=0;
			num1=fp1(s[i][j],i,j);
			num2=fp2(s[i][j],i,j);
			num3=fp3(s[i][j],i,j);
			num4=fp4(s[i][j],i,j);
			int num=max(max(num1,num2),max(num3,num4));
			if(s[i][j]=='r'){
				maxr=max(maxr,num);
			}else if(s[i][j]=='p'){
				maxp=max(maxp,num);
			}
		}
	}
	if(maxr>=4){
		cout<<"kou"<<endl;
		return ;
	}
	if(maxp>=4){
		cout<<"yukari"<<endl;
		return ;
	}
	cout<<"to be continued"<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	//cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

第六题,小红的数组操作

二分搜索贪心策略 。要求在进行  k 次操作后,使数组的最大值尽可能小。我们需要思考如何分配这  k 次操作,使得最终的数组的最大值最小。一个有效的思路是尝试找到一个最小的最大值,使得在 k  次操作内可以将数组中的所有元素降低到不超过这个值。执行二分查找后检查答案是否符合题意要求即可。本题难度不高,但是不太容易想到二分这一思路。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
	int n, k, x;
    cin >> n >> k >> x;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
    	cin >> a[i];
	}
    int low = a[0] - k * x;
	int high = *max_element(a.begin(), a.end());
    while (low < high) {
        int mid = (high + low) / 2, tmp = 0;
        for (int i = 0; i < n; ++i) {
        	if (a[i] > mid) {
        		tmp += (a[i] - mid + x - 1) / x; // (a[i] - mid) / 2 的向上取整
			}
		}
        if (tmp <= k) high = mid;
        else low = mid + 1;
    }
    cout << low << endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	//cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值