ZISUOJ C语言-结构体

本文介绍了C++新手如何使用刚学到的结构体和排序算法(如sort、冒泡排序)解决一系列编程问题,包括数字乘积排序、学生成绩排列、平方和排序、字符1个数统计、日期排序、火星数转换和贪心策略应用(活动选择与金银岛问题)。
摘要由CSDN通过智能技术生成

说明:

博主是ZISU在校学生,刚学C/C++才3个月,为了记录自己的学习过程和分享思路,故写一些博客。当然我的代码许多时候不是最优解,欢迎大家评论留言一起学习。如果有友友想提交这些题试试自己的思路啥的,可以私我,因为外校友友应该是登陆不进咱们的平台的。对于搜索到本博客的同校友友,切勿直接照抄,理解了再自己码字码上去。

题目列表:

问题 A: 数字乘积排序

 思路:通过刚学习的结构体来写,一个结构体里存放数字的值以及它数字乘积的值,通过排序然后输出即可。
参考题解1:(使用C++<algorithm>中的sort()函数进行排序)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;//N=(int)1005
struct number{
	int value;
	int product;//product表示value的乘积值 
}num[N];
int cal_product(int value){	//计算乘积函数 
	int product = 1;
	while(value!=0){
		product*=value%10;
		value /= 10;
	}
	return product;
}
bool cmp(number num1,number num2){
	//如果两个整数的数字乘积不相等,则数字乘积小者排在前
	if(num1.product != num2.product) return num1.product < num2.product;
	else return num1.value < num2.value;//若数字乘积相等,则整数值小者排在前
}
int main(){
	//问题 A: 数字乘积排序
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int n;cin >> n;
	for(int i = 1;i<=n;i++) cin >> num[i].value;
	for(int i = 1;i<=n;i++) num[i].product = cal_product(num[i].value);
	sort(num+1,num+1+n,cmp);//排序
	for(int i = 1;i<=n;i++){
		//实现输出时每个数之间用一个空格隔开,行末无空格
		if(i == 1) cout << num[i].value;
		else cout << ' ' << num[i].value;
	}
	return 0;
}

参考题解2:(使用老方法冒泡排序)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;//N=(int)1005
struct number{
	int value;
	int product;//product表示value的乘积值 
}num[N];
int cal_product(int value){	//计算乘积函数 
	int product = 1;
	while(value!=0){
		product*=value%10;
		value /= 10;
	}
	return product;
}
int main(){
	//问题 A: 数字乘积排序
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int n;cin >> n;
	for(int i = 1;i<=n;i++) cin >> num[i].value;
	for(int i = 1;i<=n;i++) num[i].product = cal_product(num[i].value);
	number temp;
	for(int i = 1;i<=n-1;i++){//冒泡排序 
		for(int j = 1;j<=n-i;j++){
			if(num[j].product>num[j+1].product||num[j].product==num[j+1].product&&num[j].value>num[j+1].value){
				temp = num[j];
				num[j] = num[j+1];
				num[j+1] = temp;
			}
		}
	}
	for(int i = 1;i<=n;i++){
		//实现输出时每个数之间用一个空格隔开,行末无空格
		if(i == 1) cout << num[i].value;
		else cout << ' ' << num[i].value;
	}
	return 0;
}

问题 B: 排列学生成绩

 

思路:开一个存放学生信息的结构体,包含学生姓名和5门成绩和平均分,然后使用sort()排序即可

参考题解:(这里就不给出使用冒泡排序的方法了,冒泡排序的方法跟A题同理)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+5;//N=(int)105
struct student{
	string name;//使用string方便后续的排序,使用char name[30]也可,但是会麻烦一点 
	int score[6];//使用score[1]到score[5],大小需要开6个,score[0]不用 
	double avg_score;//平均成绩 
}stu[N];
double cal_avg_score(student stu1){//计算平均成绩函数 
	double sum = 0;
	for(int i = 1;i<=5;i++) sum+=stu1.score[i];//计算总分 
	return sum/5;
}
bool cmp(student stu1,student stu2){
	//如果平均分不相等,则根据平均分从大到小排序 
	if(stu1.avg_score!=stu2.avg_score) return stu1.avg_score>stu2.avg_score;	
	else return stu1.name<stu2.name;//如果平均分相等,则根据名字的字典序从小到大排序 
}
int main(){
	//问题 B: 排列学生成绩
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int index = 1;
	while(cin >> stu[index].name){
		for(int i = 1;i<=5;i++) cin >> stu[index].score[i];
		index++;
	}
	//计算每个学生的平均成绩 
	for(int i = 1;i<index;i++) stu[i].avg_score = cal_avg_score(stu[i]); 
	sort(stu+1,stu+index,cmp);//从stu[1]排序到stu[index-1],排序规则为cmp函数 
	for(int i = 1;i<index;i++){
		if(stu[i].avg_score < 60) break;//如果平均成绩开始小于60,则跳出循环,节省计算资源
		cout << i << ' ' << stu[i].name << '\n';
	}
	return 0;
}

问题 C: 平方和排序

思路:同理,开一个存放整数信息的结构体,包含它的值以及它的平方和,再采用sort()排序,最后输出结果即可

 参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+5;//N=(int)105
struct number{
	int value;
	int sum_of_squares;//平方和 
}num[N];
int cal_sum_of_squares(int value){//计算平方和函数 
	int sum = 0;
	while(value!=0){
		sum += pow(value%10,2);
		value /= 10;
	}
	return sum;
}
bool cmp(number num1,number num2){//按照平方和大小排序,平方和大小相等不作处理 
	return num1.sum_of_squares<num2.sum_of_squares;
}
int main(){
	//问题 C: 平方和排序
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int n;
	while(cin >> n){
		if(!n) break;
		for(int i = 1;i<=n;i++) cin >> num[i].value;
		//计算每个数的平方和 
		for(int i = 1;i<=n;i++) num[i].sum_of_squares = cal_sum_of_squares(num[i].value);
		sort(num+1,num+1+n,cmp);//从num[1]到num[n]排序,排序规则为cmp 
		for(int i = 1;i<=n;i++) cout << num[i].value << ' ';
		cout << '\n';
	}
	return 0;
}

问题 D: 按1的个数排序

思路:注意不能使用整数类型来接收输入,应当使用字符数组或字符串来接收,同理开一个包含数字字串的结构体,包含数字字串和它1的个数,使用sort()排序,再输出结果即可

 参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+5;//N=(int)105
struct number{
	string str;
	int num_of_one;//字串'1'的个数 
}num[N];
int cal_num_of_one(string str){//计算字串'1'的个数函数 
	int res = 0;
	//遍历字符串,有出现字符'1'则res++ 
	for(int i = 0;i<str.length();i++) if(str[i] == '1') res++;
	return res;
}
bool cmp(number num1,number num2){
	//按1的个数从小到大的顺序进行排序 
	if(num1.num_of_one != num2.num_of_one) return num1.num_of_one<num2.num_of_one;
	else return num1.str<num2.str;//若1的个数相同,则按ACSII顺序从小到大输出
}
int main(){
	//问题 D: 按1的个数排序
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int index = 1;
	while(cin >> num[index].str) index++;//读数字字串 
	//计算各个字串'1'的个数
	for(int i = 1;i<index;i++) num[i].num_of_one = cal_num_of_one(num[i].str);
	sort(num+1,num+index,cmp);//从num[1]到num[index-1]排序,排序规则为cmp 
	for(int i = 1;i<index;i++) cout << num[i].str << '\n'; 
	return 0;
}

问题 E: 按日期排序

思路:开一个存放日期的结构体,包含月、日、年,然后使用sort()函数排序,最后输出即可

参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;//N=(int)1005
struct date{
	int month,day,year;//月,日,年 
}d[N];
bool cmp(date d1,date d2){//按日期先后排序,早的排在前面,晚的排在后面 
	//如果年份不同,把年份小的排在前面 
	if(d1.year!=d2.year) return d1.year<d2.year;
	//如果年份相同,月份不同,则把月份小的排在前面 
	else if(d1.year==d2.year&&d1.month!=d2.month) return d1.month<d2.month;
	//如果年份和月份都相同,则把日(day)小的排在前面 
	else return d1.day<d2.day;
}
int main(){
	//问题 E: 按日期排序 
	//这题为了方便输入输出,我们要使用scanf()和printf(),就不能使用快读了 
//	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int index = 1;
	//读入日期 
	while(~scanf("%d/%d/%d",&d[index].month,&d[index].day,&d[index].year)) index++;
	sort(d+1,d+index,cmp);//从num[1]到num[index-1]排序,排序规则为cmp 
	//输出排序后的日期 
	for(int i = 1;i<index;i++) printf("%02d/%02d/%04d\n",d[i].month,d[i].day,d[i].year);
	return 0;
}

问题 F: 火星数排序

思路:把输入的火星数字进行替换成地球数字,都存放在同一个结构体中,然后sort()排序输出

 参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;//N=(int)1005
struct number{
	int Mars,earth;//Mars表示火星数,earth表示地球数 
}num[N];
int transformation(int Mars){//将火星数转换为地球数 
	int order = 0,earth = 0;//order为阶数即作为10的指数,earth为要返回的地球数 
	while(Mars != 0){
		//一一数值对应转换 
		if(Mars%10==0) earth += 0*pow(10,order);
		else if(Mars%10==8) earth += 1*pow(10,order);
		else if(Mars%10==1) earth += 2*pow(10,order);
		else if(Mars%10==5) earth += 3*pow(10,order);
		else if(Mars%10==2) earth += 4*pow(10,order);
		else if(Mars%10==3) earth += 5*pow(10,order);
		else if(Mars%10==9) earth += 6*pow(10,order);
		else if(Mars%10==4) earth += 7*pow(10,order);
		else if(Mars%10==7) earth += 8*pow(10,order);
		else earth += 9*pow(10,order);
		order++;//阶数累加 
		Mars /= 10;
	}
	return earth;
}
bool cmp(number num1,number num2){//根据地球数从小到大排序 
	return num1.earth<num2.earth;
}
int main(){
	//问题 F: 火星数排序 
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int Case;cin >> Case; 
	while(Case--){
		int n;cin >> n;
		memset(num,0,sizeof num);//初始化num为0 
		for(int i = 1;i<=n;i++) cin >> num[i].Mars;//读火星数 
		//计算火星数对应的地球数 
		for(int i = 1;i<=n;i++) num[i].earth = transformation(num[i].Mars);
		sort(num+1,num+1+n,cmp);//对num[1]到num[n]根据cmp规则排序 
		for(int i = 1;i<=n;i++){
			//格式化输出 
			if(i == 1) cout << num[i].Mars;
			else cout << ' ' << num[i].Mars;
		}
		cout << '\n';
	}
	return 0;
}

问题 G: 活动选择(tan5)

思路:开一个包含活动开始时间、结束时间、序号的结构体,使用贪心算法根据活动的结束时间从小到大排序,然后按时间从小到大遍历活动并输出即可。

参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+5;//N=(int)105
struct activity{
	int begin,end,index;//开始时间,结束时间,序号 
}a[N];
bool cmp(activity a1,activity a2){
	return a1.end<a2.end;//根据结束时间从小到大排序 
}
int main(){
	//问题 G: 活动选择(tan5)
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int n;cin >> n;
	//读开始时间和结束时间 
	for(int i = 1;i<=n;i++) cin >> a[i].begin >> a[i].end;
	for(int i = 1;i<=n;i++) a[i].index = i;//赋值序号 
	sort(a+1,a+1+n,cmp);//从a[1]到a[n]按cmp规则排序 
	int now = 0,type = 0;//now为当前时间,type用于格式化输出,type为0的时候为第一次活动,type为1的时候为后续活动 
	for(int i = 1;i<=n;i++){//贪心 
		if(now<=a[i].begin){
			now = a[i].end;
			if(!type) cout << a[i].index;
			else cout << ',' << a[i].index;
			type = 1;
		}
	}
	return 0;
}

 问题 H: 金银岛问题(tan9)

思路:开一个存放金属重量、金属总价值、金属单位重量价值的结构体,按照金属单位重量价值从大到小排序。使用贪心的思想把每单位重量价值最大的金属先带走,没法全部带走的就带走能带走的部分。然后输出带走金属的总价值即可。

 参考题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+5;//N=(int)105
struct medal{
	int n,v;//n代表金属重量,v代表金属总价值 
	double value_of_unit_mass;//value_of_unit_mass代表单位重量的价值 
}m[N];
double cal_value_of_unit_mass(medal m1){//计算金属的单位重量的价值 
	double res;
	res = 1.0*m1.v/m1.n;//强制类型转换:int=>double 
	return res;
}
bool cmp(medal m1,medal m2){//根据金属的单位重量的价值从大到小排序 
	return m1.value_of_unit_mass>m2.value_of_unit_mass;
}
int main(){
	//问题 G: 活动选择(tan5)
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//要用scanf()和printf()不能使用快读
	int k;cin >> k;
	while(k--){
		int w,s;cin >> w >> s;
		for(int i = 1;i<=s;i++) cin >> m[i].n >> m[i].v;
		//计算金属的单位重量 
		for(int i = 1;i<=s;i++) m[i].value_of_unit_mass = cal_value_of_unit_mass(m[i]);
		sort(m+1,m+1+s,cmp);//从m[1]到m[s]按cmp规则排序 
		int now_weight = 0;//now_weight为当前口袋的重量 
		double now_value = 0;//now_value为当前口袋的总价值 
		for(int i = 1;i<=s;i++){//贪心 
			if(now_weight+m[i].n<=w){//如果口袋当前放得下所有该种金属,则全部带走放进口袋 
				now_weight+=m[i].n;
				now_value += m[i].v;
			}else{//如果当前口袋放不下所有该种金属,则能放下多少放多少
				now_value += 1.0*(w-now_weight)/m[i].n*m[i].v;
				break;
			}
		}
		cout << fixed << setprecision(2) << now_value << '\n';//格式化输出,保留小数点后两位 
	}
	return 0;
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Beau_Will

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值