欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第二届传智杯复盘 Java(自闭)代码

程序员文章站 2022-05-29 20:46:16
...
诶,过去一天了,昨天真的让我知道了不能小看任何一道题(差点就爆零了!!)。
这里来复盘一下自己比赛的时候出现的错误

 (谁说传智杯简单的,我过去就是一脚

软件工程实习:

题目描述:
某大学的《软件工程》必修课分为理论和实践部分。理论部分由该校教授完成授课;而实践部分是由第三方的公司主导,需要同学们在五周时间内自学 HTML、css、JavaScript、vue、Python、django 等技术,并组队完成一个真实的互联网商业应用。
参与这个课程的有 n(0≤n≤1000) 个学生,分成了不超过 26 个队伍,每个队伍用 A 到 Z 来表示。每个队伍都会完成一个项目,并以队伍为单位,给所有队伍(包括自己队伍)打分,范围是 0 到 100 的整数。
为了平息学生对这门课产生的出多问题的不满(比如工作量太大、时间过于紧张、考核方式不公平等),老师决定使用一种“看起来”很公平的方式来决定每组队伍的项目得分:
对于某个队伍,首先计算所有队伍(包括自己)给这个队伍评分的平均值,然后剔除掉和这个平均值差别超过 15 分的评分(保证不会出现所有的评分全部被剔除的情况),最后再对剩余的评分求平均值,四舍五入取整后作为这个队伍的项目得分。
对于每一个同学,我们已经得知他们的队伍代号和理论成绩(也是 0 到 100 分的整数)。这位同学的最后得分就是 60% 的理论成绩加上 40% 的所在队伍的项目得分,然后四舍五入取整。
现在老师想知道所有同学的分数排行。请按最后得分从高到低的顺序,输出每位同学的得分和他所在的队伍。
输入格式:
第二届传智杯复盘 Java(自闭)代码

输出格式:
输出 n 行表示答案,得分高的同学优先输出,得分相同时队伍编号较小的同学优先输出。对于每一行,先输出这位同学成绩,然后输出代表他的队伍编号的大写英文字母。

易错点:
(1)首先拿到这个题,这么长的题目,就让我烦躁得很,也是因为自己第一次参加这种正式性的比赛,诶,有点紧张吧还是,首先我们必须得把题目认认真真地读完。
(2)第一个易错点,当我们剔除掉平均分后我们必须得四舍五入一下,然后当我们计算出来每个同学的成绩时,我们还是必须得四舍五入一下!
(3)第二个易错点,相信大家也看见了,我上面标注出来了,得分相同的时候队伍编号小的优先输出啊!!!!(这里我比赛的时候无限WA,眼睛瞎了)
(4)第三个易错点,在每个队伍打分的时候,他不是说每一行就是这一个队伍的得分啊!他是说每一行是每一个队伍给别的队伍打的分!!
例如:
70 90 100
95 88 85
30 47 100
A的得分是:70 95 30
B的得分是:90 88 47
依次类推,而不是说什么A的得分是 70 90 100 !! (害 - - 给自己长个记性吧,这个题WA了很多发,最后心态都炸了,比赛可想而知)
最后贴出代码:

package 传智杯第二届;
import java.util.*;
public class Test1 {
	static int n,k;
	static int a[][] = new int[30][30]; // 每个队伍互相打的分数
	static double avg[] = new double[30]; // 每个队伍平均分
	static double sum[] = new double[30]; // 每个队伍分数总和
	static int cnt[] = new int[30]; // 每个队伍现在有效得分次数
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		k = sc.nextInt();
		student stu[] = new student[n];
		for(int i = 0;i < n;i++){
			stu[i] = new student();
			stu[i].t = sc.nextInt();
			stu[i].no = sc.next().charAt(0);
		}
		for(int i = 0;i < k;i++){
			for(int j = 0;j < k;j++){
				a[j][i] = sc.nextInt();
				sum[j] += a[j][i]; // 每个队伍的成绩和
			}
		}
		for(int i = 0;i < k;i++)
			avg[i] = sum[i]/(double)k;
		Arrays.fill(cnt,k);
		for(int i = 0;i < k;i++)
			for(int j = 0;j < k;j++){
				if(Math.abs(avg[i]-(double)a[i][j]) > 15){
					sum[i] -= a[i][j];
					cnt[i]--;
				}
			}
		for(int i = 0;i < k;i++)
			avg[i] = (int)(sum[i]/(double)cnt[i]+0.5);
		for(int i = 0;i < n;i++)
			stu[i].t = (int)(stu[i].t*0.6+avg[stu[i].no-'A']*0.4+0.5);
		Arrays.sort(stu);
		for(int i = 0;i < n;i++)
			System.out.println(stu[i].t+" "+stu[i].no);
		sc.close();
	}
}
class student implements Comparable{
	int t;
	char no;
	public int compareTo(Object b){
		student a = (student)b;
		if(this.t < a.t)
			return 1;
		else if(this.t == a.t){
			if(this.no > a.no)
				return 1;
			else
				return -1;
		}
		else return -1;
	}
}

程序员节发橙子

题目描述:
第二届传智杯复盘 Java(自闭)代码
输入格式:
第二届传智杯复盘 Java(自闭)代码
输出格式:
输出答案,也就是需要最少准备多少个橙子。

错误思想:
这个题我的想法居然是找出最小成绩的那个同学,然后以他为标准,分别向两边去扩散,殊不知这个是完全错误的。
当然对于样例是没一点毛病
样例:
5
3 4 5 4 3
输出 9 // 1 2 3 2 1 没一点毛病
当时如果是 6 1 9 7 6
这种思想的话给的橘子数为 : 2 1 2 1 0
居然出现0了!

正确的思想是:
(1)我们先假设每个人先发一个橘子,因为每个人至少要收到一个橘子
(2)从左到右扫描一遍,然后如果右边的成绩比左边的大,不用说这个人分的橘子数肯定是左边那个人+1,我们不要在这个时候判断右边比左边小的,因为这个可能会导致出现负数。
(3)最后从右向左扫描一遍,如果左边比右边大的话,a[i-1] = max(a[i-1],a[i]+1)相等的话:
a[i-1] = max(a[i-1],a[i]) 相信也挺好理解的

代码:

package 传智杯第二届;
import java.io.*;
public class Test2 {
	static int n;
	static int a[] = new int[1000010];
	static int num[] = new int[1000010];
	public static void main(String[] args) throws IOException{
		StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
		re.nextToken(); n = (int)re.nval;
		long ans = 0;
		for(int i = 1; i <= n;i++){
			re.nextToken();
			a[i] = (int)re.nval;
		}
		for(int i = 1;i < n;i++){
			if(a[i] < a[i+1])
				num[i+1] = num[i]+1;
			else if(a[i] == a[i+1])
				num[i+1] = num[i];
		}
		for(int i = n;i > 1;i--){
			if(a[i] < a[i-1])
				num[i-1] = Math.max(num[i-1],num[i]+1);
			else if(a[i] == a[i-1])
				num[i-1] = Math.max(num[i-1],num[i]);
		}
		for(int i = 1;i <= n;i++)
			ans += num[i];
		pr.println(ans+n);
		pr.flush();
	}
}

众数出现的次数

题目描述:
第二届传智杯复盘 Java(自闭)代码
输入格式:
第二届传智杯复盘 Java(自闭)代码
输出格式:
第二届传智杯复盘 Java(自闭)代码
首先这个题我感觉可能是这套题最没有坑点的题了吧,题意简单明了,但是这个题还是考察了对于Map的使用吧。。 听说有大佬没用Map , 害 不过我这种菜鸡也只能这样了
分析题目:
(1)首先这个题有1e6的同学 每个同学都有可能出的数字都有2个,我们如果把这些存到这个数组中好了,写到这里我知道为什么可以不用Map了。。我是傻逼 开个2*1e6的数组排序一下就可以记录了吧。
(2)因为我当时排序的时候我想到的是桶排,看到数字1e9我以为排序不行,诶,dbqwtcl。
(3)不过这个题我们还是可以用map的!我们可以把每个数和每个数出现的次数以键值对的形式存进map中,然后我们需要的答案就是value最大值的那个数字对应的键

代码:

package 传智杯第二届;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
public class Test3 {
	static int n;
	static int a[] = new int[1000010];
	static int b[] = new int[1000010];
	static HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
	public static void main(String[] args) throws IOException{
		StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
		re.nextToken(); n = (int)re.nval;
		for(int i = 1;i <= n;i++){
			re.nextToken();
			a[i]  = (int)re.nval;
			re.nextToken();
			b[i] = (int)re.nval;
			b[i] = a[i]^b[i];
			map.put(a[i],0);
			map.put(b[i],0);
		}
		for(int i = 1;i <= n;i++){
			if(a[i] != b[i]){
				map.put(a[i],map.get(a[i])+1);
				map.put(b[i],map.get(b[i])+1);
			}
			else
				map.put(a[i],map.get(a[i])+1);
		}
		int k = 0;
		long ans = 0;
		for(Entry<Integer,Integer> entry : map.entrySet()){ // 这里可能比较关键 使用Entry可以很好很快速的返回每一个键值对的键与值
			if(entry.getValue() > ans){
				ans = entry.getValue();
				k = entry.getKey();
			}
			else if(entry.getValue() == ans && entry.getKey() < k)
				k = entry.getKey();
		}
		pr.println(k);
		pr.flush();
	}
}

如果有人不知道里面的快读快输出,可以参考一下这篇博客哦
第四题暂时没写,写了在补吧,先咕着