蓝桥杯VIP试题-算法训练-特等奖学金

package exercise1;

import java.util.Scanner;

/*
资源限制
时间限制:1.0s   内存限制:256.0MB

问题描述
  土豪大学每年都会给学生颁发巨额的特等奖学金,当然,获奖的前提是要足够优秀。
这所大学有n名学生,他们中的每个人都会在m门必修课的每门课上获得一个百分制的整数成绩(0-100),
到了期末教务长会获得所有学生在所有必修课上的成绩报告,他会从中挑选出最优秀的k位学生,
并给他们颁发奖学金。
  教务长认为,某个学生只要有一门课不及格(分数<85),他就丧失了获得奖学金的资格。
教务长会给所有科目按照重要性排序,在所有拥有获得奖学金资格的学生中,教务长更喜欢在更
重要的科目中取得高分的学生,并依此将学生排序(即对于某两名学生,在最重要的科目中取得
更高分的学生排在前面;如果两人在最重要的科目中取得相同的分数,则比较次重要的科目;
若再相同则比较第三重要的科目……一直下去)。
  以前土豪大学的学生数量并不多,教务长就用纸笔计算谁将获得奖学金;今年大学扩招了,
教务长意识到用纸笔计算太复杂了,你能帮他解决这个问题吗?说不定教务长高兴了就给你也
发一份奖学金(⊙o⊙)哦!(注意:获奖学生数量可能小于k)

输入格式
  输入数据第一行为三个整数n、m、k,用空格隔开;
	第二行至第(n+1)行是学号分别为1、2……n的同学的m门课的成绩(m门课已按重要性排序)
	用空格隔开(输入保证每两人的分数不完全相同)。
	
输出格式
  输出一行为获奖同学的学号,按排名从前到后排序,用空格隔开。
样例输入
10 2 7
99 87
96 79
93 99
88 88
90 87
90 86
90 88
88 90
91 100
100 85

样例输出
10 1 3 9 7 5 6
数据规模和约定
  0<n≤1000,0<m≤100,0<k≤n
 */
public class Award
{
	public static void main(String[] args)
	{
		/*
		 * 得到这样的数组,第一行表示每一个人的第一门课的成绩
		 * 				  第二行表示每一个人的第二门课的成绩
		 */
		Scanner in=new Scanner(System.in);
		int n,m,k;	//一共有n个学生,m门学科,要选k个学生当优秀学生颁奖
		n=in.nextInt();
		m=in.nextInt();
		k=in.nextInt();
		
		int[][] arr=new int[m][n+1];
		int[] unpass=new int[n+1];		//unpass用来标记该学生有没有每一科超过85
		
		int temp;
		for (int x = 1; x < arr[0].length; x++)
		{
			for(int y=0;y<arr.length;y++)
			{
				temp=in.nextInt();
				arr[y][x]=temp;
				if(temp<85)
				{
					unpass[x]=-1;
				}
			}
		}
		in.close();
		/*
		 * 这里是想找出k个人出来,经过一次测试发现,如果找不够k个人,就是
		 * 要颁奖的人数不够k个人,比如很多人没有考过85分,所以实际颁奖的人就会少了
		 * 后面如果没有判断index是否等于0,就有可能会输出很多0,这也是为什么空出一列的原因
		 */
		for(int stu=0;stu<k;stu++)
		{
			int maxscore=0;
			int index=0;
			for(int x=1;x<arr[0].length;x++)
			{
				//如果发现成绩更高的就记录成绩和学生的位置(id)
				if(unpass[x]!=-1&&arr[0][x]>maxscore)
				{
					maxscore=arr[0][x];
					index=x;
				}
				//如果相等的就在没有超出科目数量情况下比较次要的科目谁的成绩高
				if(unpass[x]!=-1&&arr[0][x]==maxscore &&index!=x)
				{
					for(int subject=1;subject<arr.length;subject++)
					{
						//这两个if就是后面的科目比较出来了
						if(arr[subject][x]>arr[subject][index])
						{
							index=x;
							break;
						}
						if(arr[subject][x]<arr[subject][index])
						{
							break;
						}
					}
				}
			}
			//当这个学生已经领奖了,就加入不及格序列,让他后面不参加竞赛
			unpass[index]=-1;
			if(index!=0)
			{
				System.out.print(index+" ");				
			}
		}
		
	}
}



//========================
//下面是走的弯路
		/*
		 * 下面进行排序,利用插入排序,将第一门课按照分数进行排名
		 * 最后面一行是学生对应的id,排名的时候id也会跟着排名换位置
		 * 但是后面发现这样子要动的数据太多,不仅仅是第一门课成绩和学生的id要改变
		 * 学生的每一门课的数据都要跟着排名的改变而变动,时间复杂度很大
		 */
//		for(int x=2;x<arr[0].length;x++)
//		{
//			int insert=arr[0][x];
//			int id=arr[m][x];
//			int index=x;
//			while(index-1>=1&& arr[0][index-1]<insert)
//			{
//				arr[0][index]=arr[0][index-1];
//				arr[m][index]=arr[m][index-1];
//				index--;
//			}
//			if(index!=x)
//			{
//				arr[0][index]=insert;
//				arr[m][index]=id;
//			}
//		}
//		for(int i=1;i<arr[0].length;i++)
//		{
//			int tempcopy=arr[0][i];
//			int index=i;
//			while(index+1<arr[0].length&&arr[0][index+1]==tempcopy)
//			{
//				index++;
//			}
//			if(i!=index)
//			{
//				
//			}
//		}
//		System.out.println(Arrays.toString(arr[0]));
//		Change(0, arr, m,1,arr[0].length);
//	}
//	public static void Change(int subject,int[][] arr,int m,int start,int end)
//	{
//		for(int x=start;x<end;x++)
//		{
//			int insert=arr[subject][x];
//			int id=arr[m][x];
//			int index=x;
//			while(index-1>=start&& arr[subject][index-1]<insert)
//			{
//				arr[subject][index]=arr[subject][index-1];
//				arr[m][index]=arr[m][index-1];
//				index--;
//			}
//			if(index!=x)
//			{
//				arr[subject][index]=insert;
//				arr[m][index]=id;
//			}
//		}
//		for(int i=start;i<end;i++)
//		{
//			int tempcopy=arr[subject][i];
//			int index=i;
//			while(index+1<arr[subject].length&&arr[subject][index+1]==tempcopy)
//			{
//				index++;
//			}
//			if(i!=index&&subject+1 <m)
//			{
//				Change(subject+1, arr, m,i,index+1);
//			}
//			i=index;
//		}
//		System.out.println(Arrays.toString(arr[0]));
//		System.out.println(Arrays.toString(arr[1]));
//		System.out.println(Arrays.toString(arr[2]));
//		System.out.println("===============");
//	}
//}
/*
测试数据
2 3 2 89 99 87 100 90 98

10 2 7
99 87
96 79
93 99
88 88
90 87
90 86
90 88
88 90
91 100
100 85
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ReflectMirroring

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

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

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

打赏作者

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

抵扣说明:

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

余额充值