说明:
博主是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;
}