【PTA刷题】乙级 1066 To 1085

PAT竞赛题解精粹
本文精选PAT竞赛经典题目解析,覆盖图像过滤、试密码、微博转发抽奖等算法题,探讨高效解题策略,深入分析代码实现细节,分享C/C++编程实战经验。

B1066.图像过滤 8min
签到题。 用cin输入超时挂了一个点(400ms都挂了),换成scanf只用了100ms。所以有时候cincout超时挂了可以用scanf来试试

/*B1065*/
#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{	
	int M, N, A, B, R;
    scanf("%d %d %d %d %d",&M,&N,&A,&B,&R);
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N; j++)
		{
			int p;
			scanf("%d ",&p);
			if (p >= A && p <= B)
				p = R;
			if (j != N - 1)
				printf("%03d ", p);
			else
				printf("%03d\n", p);
		}
	}
	return 0;
}

B1067.试密码 11min
自己做挂了两个点,原因是用户尝试输入的密码里面可能含有空格,干扰了cin>>str的读取。
所以要用getline来读。但是要注意第一行的输入里面最后行尾也有个回车键,这个回车键会让getline读空,因此需要用一个getchar()来消除这个回车的影响。

/*B1067*/
#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;

int main()
{	
	string ans;
	int N,flag = 0;
	cin >> ans >> N;
	getchar();

	for (int i = 0; i < N; i++)
	{
		string str;
		getline(cin, str);
		if (str == ans)
		{
			flag = 1;
			cout << "Welcome in\n";
			break;
		}
		else if (str == "#")
		{
			flag = 1;
			break;
		}
		else
			cout << "Wrong password: " << str<<"\n";
	}
	if (flag == 0)
		cout << "Account locked\n";


	return 0;
}

B1069.微博转发抽奖 23min
有一个点一直过不去。我怀疑是抽到某人时,往后移一位后的那个人也被重复抽奖了。
柳神用的map,map<string, int > mapp相当于用string做角标,控制int的值。map[str] ==1 表示,在map中已经出现过str。

/*B1069*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int main()
{	
	int M, N, S;
	cin >> M >> N >> S;

	vector<string> All;
	vector<string> res;
	for (int i = 0; i < M; i++)
	{
		string str;
		cin >> str;
		All.push_back(str);
	}
	
	int i;
	for ( i = S-1; i < M; i = i + N)
	{
		if (find(res.begin(), res.end(), All[i]) == res.end())//没在res找到
		{
			cout << All[i] << "\n";
			res.push_back(All[i]);
		}
		else {
			cout << All[i + 1] << "\n";
			i++;
		}
	}

	if (res.size() == 0)
		printf("Keep going...");

		

	return 0;
}

B1070.结绳 19min

/*B1067*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>

using namespace std;

int main()
{	
	int N;
	cin >> N;
	vector<int> ori;
	for (int i = 0; i < N; i++)
	{
		int num;
		cin >> num;
		ori.push_back(num);
	}

	sort(ori.begin(), ori.end());

	double a = (ori[0] + ori[1]) / 2;
	ori.erase(ori.begin());
	ori.erase(ori.begin());
	while (ori.size()>0)
	{	
		a = (a+ ori[0]) /2 ;
		ori.erase(ori.begin());	
	}
	cout << (int)a ;


	return 0;
}

B1071.小赌怡情 23min
题目很简单,挂了测试点莫名其妙的。

/*B1071*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int main()
{	
	int T, K;
	cin >> T >> K;

	for (int i = 0; i < K; i++)
	{
		int n1, b, t, n2;
		int win = 0;
		cin >> n1 >> b >> t >> n2;

		if (T <= 0)
		{
			printf("Game Over\n");
			break;
		}

		if (t > T)
		{
			printf("Not enough tokens.  Total = %d.\n", T);
			continue;
		}

		if (n2 > n1 && b == 1)
			win = 1;
		else if (n2 < n1 && b == 0)
			win = 1;
		
		if (win == 1)
		{	
			T += t;
			printf("Win %d!  Total = %d.\n", t, T);
		}
		else
		{
			T -= t;
			printf("Lose %d.  Total = %d.\n", t, T);
		}
	}

	return 0;
}

B1072.开学寄语 15min
有一个价值两分的特殊点没过。

/*B1071*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdio.h>


using namespace std;

int main()
{	
	int N, M;
	cin >> N >> M;
	
	vector<int> obj(M);
	for (int i = 0; i < M; i++)
		cin>>obj[i];

	int StuNum = 0, ProblemNum = 0;
	for (int i = 0; i < N; i++)
	{
		int flag = 0;
		string Name;
		int ObjNum;
		cin >> Name >> ObjNum;
		

		vector<int> res;
		for (int j = 0; j < ObjNum; j++)
		{	
			int tmp;
			cin >> tmp;
			if (find(obj.begin(),obj.end(),tmp) != obj.end())//找到了
			{
				res.push_back(tmp);
				flag = 1;
				ProblemNum++;
			}
		}
		if (flag == 1)
		{
			StuNum++;
			cout << Name << ":";
			for (int z = 0; z < res.size(); z++)
				cout << " "<<res[z];
			cout << "\n";
		}
	}
	cout << StuNum <<" "<< ProblemNum;
	return 0;
}

B1073.多选题常见计分法 more than 70min 这题选项啥交错太歧义了,柳神用二进制异或和与运算来做的,根本想不到。考试碰到这种跳过。

#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;

struct infomation
{
	int full, all, cor;
	vector<char> v;
};

struct probleminfo
{
	int times = 0;//这题几个人错了
	int option[5] = { 0 };//各个选项错误次数

};

map<int, infomation> m;
double student[1005] = { 0 };//学生得分
probleminfo problem[1005];

int main()
{
	int N, M;
	cin >> N >> M;
	for (int i = 1; i <= M; i++)//题号从1开始
	{
		infomation info;
		cin >> info.full >> info.all >> info.cor;
		for (int j = 0; j < info.cor; j++)
		{
			char tmp;
			cin >> tmp;
			info.v.push_back(tmp);
		}
		m[i] = info;
	}

	//for (int i = 1; i <= M; i++)
	//	cout << m[i].full << " ";

	scanf("\n");
	for (int stu = 0; stu < N; stu++)
	{
		for (int i = 1; i <= M; i++)
		{	
			int ans;
			int flag = 1;//默认选了的都是对的
			scanf("(%d", &ans);
			for (int j = 0; j < ans; j++)//逐选项
			{
				char tmpans;
				scanf(" %c", &tmpans);
				if (find(m[i].v.begin(), m[i].v.end(), tmpans) == m[i].v.end())//没找到这选项
				{
					flag = 0;
					problem[i].times++;//记录题号错误
					if (tmpans == 'a') problem[i].option[0]++; //记录选项错误次数
					else if (tmpans == 'b') problem[i].option[1]++;
					else if (tmpans == 'c') problem[i].option[2]++;
					else if (tmpans == 'd') problem[i].option[3]++;
					else if (tmpans == 'e') problem[i].option[4]++;
				}
			}
			if (ans < m[i].cor && flag == 1)//有漏选
				student[stu] += (double)m[i].full / (double)2;
			else if (ans == m[i].cor && flag == 1)
				student[stu] += (double)m[i].full;
			
			scanf(")");//处理掉多余字符
			if (i != M)
				scanf(" ");
			else if(i == M && stu != N-1)
				scanf("\n");
		}
	}

	for (int i = 0; i < N; i++)
		printf("%.1lf\n", student[i]);

	int maxtime = -999;
	for (int i = 1; i <= M; i++)//找maxtime
	{
		for (int j = 0; j < 5; j++)
		{
			if (maxtime < problem[i].option[j])
				maxtime = problem[i].option[j];
		}
	}
	if (maxtime == 0)
	{
		cout << "Too simple";
		return 0;
	}


	char list[5] = { 'a','b','c','d','e' };
	for (int i = 1; i <= M; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			if (maxtime == problem[i].option[j])
			{
				printf("%d %d-%c\n", maxtime, i, list[j]);
			}
		}
	}


	return 0;
}

B1074.宇宙无敌加法器 46min
一开始写了半小时挂了三个点,debug发现是两个小于N的数加起来可能大于N,所以要考虑最后一次的进位,虽然最后还是挂了一个点看不出来了。

/*B1072*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int main()
{
	string N;
	cin >> N;
	vector<int> ori(N.length());
	for (int i = 0; i < N.length(); i++)
	{
		if (N[i] == '0')
			ori[i] = 10;
		else
			ori[i] = N[i] - '0';
	}
	reverse(ori.begin(), ori.end());

	string A, B;
	cin >> A >> B;
	int Alen = A.length();
	int Blen = B.length();
	if (Alen < Blen)
		swap(A, B);

	reverse(A.begin(), A.end());
	reverse(B.begin(), B.end());
	B.append(A.length() - B.length(), '0');

	vector<int> res;
	int P = 0;//进位
	for (int i = 0; i < A.length(); i++)
	{
		int a = A[i] - '0';
		int b = B[i] - '0';
		int c = ori[i];
		int sum = a + b + P;
		P = sum / c;
		res.push_back(( sum )%c );
	}
	if (P != 0) res.push_back(P);

	if (res.size() == 0)
		cout << 0;
	else
	{
		int flag = 0;//数字开头的0
		for (int i = res.size() - 1; i >= 0; i--)
		{
			if (res[i] == 0 && flag == 0)
				continue;
			else if (res[i] != 0)
			{
				flag = 1;
				cout << res[i];
			}
			else
				cout << res[i];

		}
	}


	return 0;
}

B1075.链表元素分类 56min
挂了一个点。
柳神最后的按顺序输出很牛逼,比我的简单多了。但是难想,她把后面的那个next放在后一行输出,在单个printf中间输出了回车键。

思路:
1.用超大数组模拟实际地址,读入相应的结点。
2.根据每个结点里面保存的next,找到原链表的顺序以供半有序输出用,指针遍历整个链表。
3.在2的过程中将每个结点的实际地址分别装到三个vector中。
4.依次输出3个vector中的所有元素。实际上每个vector中相邻的元素就是排序后的新链表的相邻结点。
(但每个结点的next其实没有改变,因为我们只需要对vec操作就可以打印了,不需要再去操作具体结点)

/*B1075*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

struct Node
{
	int Data;
	int Next;
};
const int Max = 100005;
Node List[Max];

int main()
{	
	for (int i = 0; i < Max; i++)//初始化
		List[i].Next = -1;

	int FirstAdd,N, K;
	cin >> FirstAdd >> N >> K;

	for (int i = 0; i < N; i++)
	{
		int add, data, next;
		cin >> add >> data >> next;
		List[add].Data = data;
		List[add].Next = next;
	}

	vector<int> v[3];//用来存放3个分部的节点地址
	int it = FirstAdd;
	while (it != -1)
	{
		int data = List[it].Data;
		if (data < 0)
			v[0].push_back(it);
		else if (data >= 0 && data <= K)
			v[1].push_back(it);
		else
			v[2].push_back(it);
			
		it = List[it].Next;
	}

	vector<int> res;
	for (int i = 0; i < N; i++) //把仨数组按顺序拜访到一个数组里面。
	{
		if (i < v[0].size())
			res.push_back(v[0][i]);
		else if (i >= v[0].size() && i < (v[0].size() + v[1].size()))
			res.push_back(v[1][i - v[0].size()]);
		else
			res.push_back(v[2][i - (v[0].size() + v[1].size())]);
	}

	for (int i = 0; i < N; i++)
	{
		printf("%05d %d ", res[i], List[res[i]].Data);
		if (i != N - 1)
			printf("%05d\n", res[i + 1]);
		else
			printf("-1");
	}

	return 0;
}

B1076.WiFi密码 13min
注意读题。每个题目的ABCD是乱序的。
用cin做都可以不需要N。(来自柳神)
补充点:scanf按格式读取空格的时候,在实践中发现可以把回车也识别成空格。scanf("%c",&c)就严格读取了字符。关于C语言和CPP的string区别,C是char*,char[]。即字符的数组,而CPP的str是一个类。可以用c_str()函数来互相转化。
如:

char* c;
string s="1234";
c = s.c_str();

本题:

/*B1074*/
#include <iostream>
#include <vector>
#include <stdio.h>


using namespace std;


int main()
{	
	int N;
	cin >> N;

	vector<char> v;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			char tmp, ans;
			
			scanf("%c-%c ", &tmp, &ans);

			if (ans == 'T')
				v.push_back(tmp);
		}

	}

	for (int i = 0; i < v.size(); i++)
		cout << v[i] - 'A'+1;

	return 0;
}

B1077.互评成绩计算 17min
签到题

/*B1074*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;


double GetAverage(vector<int> v)
{	
	int sum = 0;
	for (int i = 1; i < v.size() - 1; i++)
		sum += v[i];
	
	double ave = (double)(sum) / (double)(v.size() - 2);
	return ave;

}

int main()
{	
	int N, M;
	cin >> N >> M;

	vector<int> res;
	for (int i = 0; i < N; i++)
	{	
		vector<int> tmp;
		int teacher, stu;
		for (int j = 0; j < N; j++)
		{
			if (j == 0) cin >> teacher;
			else
			{
				cin >> stu;
				if (stu >= 0 && stu <= M)
					tmp.push_back(stu);
			}
		}
		sort(tmp.begin(), tmp.end());
		double StuAve = GetAverage(tmp);
		int result = ((double)teacher + StuAve + 1)  / 2;
		res.push_back(result);
	}

	for (int i = 0; i < N; i++)
	{
		cout << res[i] << "\n";
	}
	return 0;
}

B1078.字符串压缩与解压 46min
在压缩部分我用了一个哨兵的小技巧(在尾端设置一个不可能出现的情况,使得for循环能用str的原末尾和一个我人为添加的末尾相比较,延续逻辑),使得程序一遍过了。柳神逻辑和我一模一样,但是更简便。比如说她在解压过程中,对NUM的计算就是先把NUM当成字符串,然后字符串末尾续上数字字符,要计算的时候才stoi();

注意当getline读不到数的时候考虑是不是前一行有回车键。 用getchar()来消除影响。

/*B1078*/
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <set>

using namespace std;

int main()
{
	char ToDo;
	cin >> ToDo;

	string str;
	if (ToDo == 'C')
	{	
		getchar();
		getline(cin, str);
		char tmp = str[0];
		int cnt = 0;
		str += '1'; //末尾哨兵
		for (int i = 1; i < str.size(); i++)
		{
			if (str[i] == tmp)
			{
				cnt++;
			}
			else
			{	
				if (cnt != 0)
					cout << cnt + 1 << tmp;
				else
					cout << tmp;
				tmp = str[i];
				cnt = 0;
			}
		}
	}
	else if (ToDo == 'D')
	{
		getchar();
		getline(cin, str);

		int num = 1;
		char tmp;
		int cnt = 0;//控制两位数,三位数
		for (int i = 0; i < str.size(); i++)
		{
			if (str[i] >= '0' && str[i] <= '9') 
			{	
				cnt++;
				if (cnt == 1)
					num = str[i] - '0';
				else
					num = num * 10 + (str[i] - '0');
	
			}
			else
			{	
				cnt = 0;
				tmp = str[i];
				if (num != 1)
				{
					for (int j = 0; j < num; j++)
						cout << tmp;
					num = 1; //初始化
				}
				else
					cout << tmp;
			}
		}
	}
	return 0;
}

B1079.延迟的回文数 36min
按部就班做比较简单。注意大数计算按位相加后,要考虑最后那位需不需要进位,如果要的话就 str = ‘1’ + str;
此外,判断是否是回文有个更简单的方法,直接将a倒置,看看是否和a本身相等。就不用像我一样判断内部了。

#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <iostream>

using namespace std;

string getsum(string a,string b)
{	
	string str,tmp;
	int flag = 0;
	int sum;
	for (int i = a.length() - 1; i >= 0; i--)
	{	
		sum = (a[i] - '0') + (b[i] - '0');
		tmp = to_string( (sum +flag) % 10);
		if (sum +flag >= 10)
			flag = 1;
		else
			flag = 0;

		str = tmp + str;
	}
	if (flag == 1)
		str = "1" + str;

	return str;
}

bool IsPalindromic(string a)
{
	if (a == "0") return true;
	int k = a.length() - 1;
	for (int i = 0; i < a.length() / 2; i++)
	{
		if (a[i] != a[k - i])
			return false;
	}
	return true;
}

int main()
{
	string a,b;
	int cnt = 0;
	cin >> a;

	while (!IsPalindromic(a))
	{
		if (cnt < 10)
		{
			b = a;
			reverse(b.begin(), b.end());
			string sum = getsum(a, b);
			cout << a << " + " << b << " = " << sum<<"\n";
			a = sum;
			cnt++;
		}
		else
		{
			cout << "Not found in 10 iterations.";
			return 0;
		}
	}

	cout << a << " is a palindromic number.";
	return 0;
}

B1080.MOOC期终成绩 46min
自己做超时一个测试点,原因是找是否已经在数组中存在的时候用了for暴力解。
柳神使用了map,在第一轮循环填入数值时,map和vec同时被填入,这样就可以在map中找是否已经出现过,并且用map的里面储存的int的数值(刚好就是角标顺序)来控制vec的元素的改写。

且补充一点:vector,set,map的Int类型元素,在未赋值的时候默认为0;
但在struct中未赋值的int类型默认为-858993460

/*B1080*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <map>

using namespace std;

struct Stu
{
	string id;
	int Gp = -1, Gm = -1, Gf = -1, G;
};


bool cmp(Stu a,Stu b)
{
	if (a.G != b.G)
		return a.G > b.G ? true : false;
	else
		return a.id < b.id ? true : false;
}

int main()
{
	int P, M, N;
	cin >> P >> M >> N;
	vector<Stu> v;
	map<string, int> idx;
	int cnt = 1;//用来标记map中每一个的角标,以对应vec

	for (int i = 0; i < P; i++)//读取Gp
	{	
		string ID;
		int score;
		cin >> ID >> score;
		if (score >= 200)
		{
			Stu s;
			s.id = ID;
			s.Gp = score;
			v.push_back(s);
			idx[ID] = cnt++;
		}
	}
	for (int i = 0; i < M; i++)//读取Gm
	{
		string ID;
		int score;
		cin >> ID >> score;
		if (idx[ID] > 0)//找到了
			v[idx[ID] - 1].Gm = score;
	}
	for (int i = 0; i < N; i++)//读取Gf
	{
		string ID;
		int score;
		cin >> ID >> score;
		if (idx[ID] > 0)
			v[idx[ID] - 1].Gf = score;
	}
	vector<Stu> res;
	for (int i = 0; i < v.size(); i++)//计算G
	{
		if (v[i].Gm > v[i].Gf) 
		{	
			double tmp;
			tmp = (double)v[i].Gm * 0.4 + (double)v[i].Gf * 0.6;
			v[i].G = (tmp+0.5) / 1;
		}
		else
			v[i].G = v[i].Gf;

		if (v[i].G >= 60)
			res.push_back(v[i]);
	}
	
	sort(res.begin(), res.end(), cmp);
	for (int i = 0; i < res.size(); i++)
	{
		cout << res[i].id << " " << res[i].Gp << " "
			<< res[i].Gm << " " << res[i].Gf << " "
			<< res[i].G << "\n";
	}
	return 0;
}

B1081.检查密码 18min
签到题
要注意,逻辑运算中,逻辑与的非门是逻辑或(想数字电路就可以了)。
此外,可以用isalnum(),来判断是否是数字或字母。
isalpha是判断是否是字母。

/*B1080*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>


using namespace std;


int IsOK(string str)
{	
	int PotN = 0, ShuziN = 0, ZimuN = 0;
	for (int i = 0; i < str.length(); i++)
	{
		if (str[i] != '.' && (str[i] < '0'|| str[i] > '9')
			&& !isalpha(str[i]))
			return 1;
		else if (str[i] == '.')
			PotN++;
		else if (str[i] >= '0' && str[i] <= '9')
			ShuziN++;
		else if (isalpha(str[i]))
			ZimuN++;
	}
	if (ShuziN == 0 && ZimuN != 0)
		return 2;
	else if (ZimuN == 0 && ShuziN != 0)
		return 3;
	else if (ZimuN != 0 && ShuziN != 0)
		return 0;

}


int main()
{
	int N;
	cin >> N;
	getchar();
	for (int i = 0; i < N; i++)
	{
		string str;
		getline(cin, str);
		if (str.length() < 6)
		{
			cout << "Your password is tai duan le.\n";
			continue;
		}

		int tmp = IsOK(str);
		if (tmp == 0)
			cout << "Your password is wan mei.\n";
		else if (tmp == 1)
			cout << "Your password is tai luan le.\n";
		else if (tmp == 2)
			cout << "Your password needs shu zi.\n";
		else if (tmp == 3)
			cout << "Your password needs zi mu.\n";


	}
	return 0;
}

B1082.射击比赛 7min
签到题

/*B1080*/
#include <iostream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

int main()
{
	int N;
	cin >> N;
	string Masterid, Noobid;
	int MinDis = 99999999, MaxDis = -1;

	for (int i = 0; i < N; i++)
	{
		string id;
		int x, y;
		cin >> id >> x >> y;
		double dis = sqrt(x * x + y* y);
		if (dis < MinDis)
		{
			Masterid = id;
			MinDis = dis;
		}
		if (dis > MaxDis)
		{
			Noobid = id;
			MaxDis = dis;
		}
	}

	cout << Masterid << " " << Noobid;
	return 0;
}

B1083.是否存在相等的差
签到题

/*B1083*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

int Cha[10005] = {0};

int main()
{
	int N;
	cin >> N;
	

	for (int i = 0; i < N; i++)
	{
		int num , tmp;
		cin >> num;
		tmp = num > i+1 ? num - (i+1) : (i+1) - num;
		Cha[tmp]++;
	}

	for (int i = 10004; i >= 0; i--)
	{
		if (Cha[i] > 1)
			cout << i << " " << Cha[i] << "\n";
	}
	return 0;
}

B1084.外观数列 fail 第二次10Min(力扣上有一模一样的题)
利用尾哨兵,感觉我的方法更优。

#include <iostream>
#include <string>
#include <vector>
#include <stdio.h>
#include <map>
#include <algorithm>

using namespace std;
int main()
{	
	string d;
	int N;
	cin >> d >> N;

	string str = d;
	for (int cnt = 0; cnt < N -1; cnt++)
	{	
		int len = str.length();
		int times = 1;
		str += "-1";
		string tmp;
		for (int i = 0; i < len; i++)
		{
			if (str[i] == str[i + 1])
				times++;
			else
			{
				tmp += str[i] + to_string(times);
				times = 1;
			}
		}
		str = tmp;
	}
	cout << str;



	return 0;
}

**B1085.PAT单位排行**  48min
答案错误了一个点扣了3分,原因未知。我用了用了map处理总分和学生数量,最后装到一个vector的结构体里面,用sort排序。

注意:柳神用了我一开始想的方法,设置两个map一个装分数一个装人数。但我一开始装入最后的res的vector的时候迭代不会用。
她是这样写的:

```cpp
//...
sum[school] += score;
cnt[school]++;

for(auto it = cnt.begin();it!= cnt.end();it++)
	res.push_back(Uni{it->first,(int)sum[it->first],cnt[it->first]})

1.结构体{1部分,2部分…}是结构体赋值的快速方法。
2.map的遍历只能用指针迭代器,返回键值用it->first,返回数值用it->second;

/*B1083*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <cctype>
#include <math.h>
#include <map>
using namespace std;

struct Uni
{
	string Uname;
	int sum;
	int StuN;
};

struct dat
{
	int score;
	int stunum;
};

bool cmp(Uni a,Uni b)
{
	if (a.sum != b.sum)
		return a.sum > b.sum ? true : false;
	else 
	{
		if (a.StuN != b.StuN)
			return a.StuN < b.StuN ? true : false;
		else
			return a.Uname < b.Uname ? true : false;
	}

}

int main()
{	
	int N;
	cin >> N;

	vector<Uni> res;
	map<string, dat> tmp;
	
	for (int i = 0; i < N; i++)
	{
		string id,uniname;
		double score;
		cin >> id >> score >> uniname;
		for (int j = 0; j < uniname.length(); j++)//全部转为小写字母
			uniname[j] = tolower(uniname[j]);

		if (id[0] == 'A')
			tmp[uniname].score += score;
		else if (id[0] == 'B')
			tmp[uniname].score += (score /1.5);
		else if (id[0] == 'T')
			tmp[uniname].score += (score * 1.5);

		tmp[uniname].stunum++;
	}
	
	for (auto it = tmp.begin(); it !=tmp.end() ; it++)
	{
		Uni uni;
		uni.Uname = it->first;
		uni.sum = it->second.score;
		uni.StuN = it->second.stunum;
		res.push_back(uni);
	}

	sort(res.begin(), res.end(), cmp);

	int rank = 1, UniNum = res.size(),cnt = 2;
	cout << UniNum << "\n";
	cout << rank << " " << res[0].Uname << " " << res[0].sum << " " << res[0].StuN<<"\n";
	for (int i = 1; i < UniNum; i++)
	{
		if (res[i].sum != res[i - 1].sum)
			rank = cnt;
		cout << rank << " " << res[i].Uname << " " << res[i].sum << " " << res[i].StuN << "\n";
		cnt++;
	}

	return 0;
}




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值