2018美团codeM

 4.分数

题目描述:小胖参加了人生中最重要的比赛——MedoC资格赛。MedoC的资格赛由m轮构成,使用常见的“加权标准分”的规则。每位选手需要参加所有的m轮的比赛。在一轮中,能取得的分数为自己的成绩除掉最高分的成绩。每个选手的总分为每一轮获得的分数乘上这一轮比赛占得比重。如果在某一轮比赛中所有人获得了零分,那么所有选手在这一轮获得的分数都为0分。比如说,资格赛一共3轮,三轮的权重分别为30%, 30%, 40%。在第一轮中,小胖获得了300分,最高分也为300分。在第二轮中,小胖获得了0分,最高分也为0分。在第三轮中,小胖获得了150分,最高分为300分,那么小胖的总分为(300/300)*30%+0*30%+(150/300)*40%=0.5。一共有n位选手参加了比赛,其中成绩最高的k位选手能够晋级到初赛。如果有多人在分数线上同分,那么系统会随机在这些同分的人中选取,选满k个晋级为止。小胖现在知道了每个选手每场比赛的成绩,但是由于他的疏忽,其中的某个人某场比赛的成绩消失了。所以更多人出线的情况变得未知起来。现在只知道成绩一定是0到C之间的一个整数(包含0和C)。小胖想知道对于每个人的出线情况是怎么样的,也就是一定能出线,一定不能出线还是有可能出线。

输入描述:第一行四个正整数n,m,k,C (m <= 6, k <= n <= 500, C <= 500)。接下来一行m个整数w1, w2, ..., wn,表示每场比赛的权重,第i场比赛的权重为wi/(w1+w2+...+wn),保证wi >= 0且1 <= w1 + w2 + ... + wn <= 1000。接下来n行每行m个整数,第i个整数表示这个选手在第i场比赛中获得的成绩。如果这个数字为-1表示这个数据丢失,保证恰好有一个-1。输出描述:n行每行输出一个1到3之间的整数。1表示一定出线,2表示一定不出线,3表示可能出线。

输入描述:第一行四个正整数n,m,k,C (m <= 6, k <= n <= 500, C <= 500)。接下来一行m个整数w1, w2, ..., wn,表示每场比赛的权重,第i场比赛的权重为wi/(w1+w2+...+wn),保证wi >= 0且1 <= w1 + w2 + ... + wn <= 1000。接下来n行每行m个整数,第i个整数表示这个选手在第i场比赛中获得的成绩。如果这个数字为-1表示这个数据丢失,保证恰好有一个-1。

输出描述:n行每行输出一个1到3之间的整数。1表示一定出线,2表示一定不出线,3表示可能出线。

示例1:

输入:
4 2 2 100
1 1
100 99
70 70
40 -1
100 39
输出:
1
3
3

2

分析:
审题注意: 题目中所说的“自己的成绩除掉最高分的成绩”,最高分的成绩 是 某一轮所有人获得成绩的最大值,比如第一轮 小A获得了10分,小B获得了100分。那么第一轮的最高分成绩为100分。
法1,暴力求解
直接穷举 缺失的数据 所有 0-C 的 C+1种可能,然后把有不同可能(0和1)的置为3,比如当缺失的数据为0时某个人必定晋级,而当取另一值时,却必定不晋级,那么将这个人设置为可能晋级。
法2,较为优化的方法
假设输入如下:
4 2 2 200
1 3
100 90
100 -1
70 70
80 66

上述输入分别对应A B C D四个人,当B第二轮成绩从0-200变化时,成绩加权平均,利用MATLAB 绘图看看在这之间的变化


从而看出缺失值在0-90变化时只有一个人的成绩在变化,并且单调递增,他在90的时候排名最高(挤下去的人最多,并且挤掉的人在这个区间不会再超过他),所以我们只需判断缺失值为0和90这两个点,又因为91-200变化率不同所以需要判断91-200这个区间所有值。

假设除缺失值外最大的值是max,故只需判断0以及[max,C] (C大于等于max) ,若max大于C ,则只判断0和C 即可。

核心代码:
int main() {
	int n, m, k, C;
	int loseRow = -1;//丢失的下标 第loseRow位选手
	int loseCol = -1;//丢失的下标 第loseCol轮成绩

	cin >> n >> m >> k >> C;

	/*数组取大一个值使得下标从1开始*/
	int **score = new int*[n + 1];
	for (int i = 0; i <= n; i++) {
		score[i] = new int[m + 1];
	}
	int *weight = new int[m + 1];
	float *weightScore = new float[n + 1];
	float *weightScoreTemp = new float[n + 1];
	int *promotions = new int[n + 1];//是否晋级 1,2,3
	int *promotionsTemp = new int[n + 1];
	int *max = new int[m + 1];//保存每轮最大值
	for (int i = 1; i <= m; i++) {
		cin >> weight[i];
		if (weight[i] < 0) {
			return -1;
		}
	}
	for (int i = 1; i <= n; i++) {
		promotions[i] = 2;
		promotionsTemp[i] = 2;//初始化为2
		for (int j = 1; j <= m; j++) {
			cin >> score[i][j];
			if (score[i][j] == -1) {
				if (loseRow != -1) {
					return -1;
				}
				loseRow = i;
				loseCol = j;
				score[i][j] = 0;
			}
		}
	}
	for (int j = 1; j <= m; j++) {
		max[j] = 0;
		for (int i = 1; i <= n; i++) {
			if (score[i][j] > max[j]) {
				max[j] = score[i][j];
			}
		}
	}
        //计算缺失值为0时,每个人的是否会晋级保存在promotions中  
	computePromotions(score, weightScoreTemp, weightScore, promotions, max, weight, n, m, k);
	int minValue = max[loseCol] > C ? C : max[loseCol];
	for (int loseValue = minValue; loseValue <= C; loseValue++) {
		if (loseValue > max[loseCol]) {
			max[loseCol] = loseValue;
		}
		score[loseRow][loseCol] = loseValue;
		//计算此种情况的每个人的是否会晋级保存在promotionsTemp中
		computePromotions(score, weightScoreTemp, weightScore, promotionsTemp, max, weight, n, m, k);
		for (int i = 1; i <= n; i++) {
			if (promotions[i] ^ promotionsTemp[i]) {
				promotions[i] = 3;
			}
			promotionsTemp[i] = 2;//初始化
		}

	}
	for (int i = 1; i <= n; i++) {
		cout << promotions[i] << endl;
	}
	delete[] max;
	delete[] promotions;
	delete[] promotionsTemp;
	delete[] weightScoreTemp;
	delete[] weightScore;
	delete[] weight;
	for (int i = 0; i <= n; i++) {
		delete[] score[i];
	}
	delete[] score;
	return 0;
}

全部评论

相关推荐

10-13 17:47
门头沟学院 Java
wulala.god:图一那个善我面过,老板网上找的题库面的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务