• 「Solution」P5759 [NOI1997]竞赛排名


    (Updated space 2020.11.26) 修改了代码中的一些错误

    解题思路

    这道题是华一高2020级信息学竞赛班在八月份一次考试中的T3。

    作为一名新初一学生,在题目里看到这么复杂的数学公式时我的心情是崩溃的。

    读题完全在读是天书

    但其实这题也没有那么难,裸的模拟

    首先,解释一下我定义的变量。

    struct stures{            // 存储每个选手的数据
    	int id;               // 选手编号
    	double yv;            // 总位置分
      double sumv;            // 总分
    }res[1005];
    int n;                    // 题目中N
    int x[1005][10] = {};     // 题目中x
    double y[1005][10] = {};  // 题目中y
    double avg[10] = {};      // 题目中avg
    

    接下来我们用文字语言来解释一下那些求和公式。

    • (j) 项竞赛的平均分 $ avg_j = frac{1}{N} sum_{i=1}^N x_{ij} $

      求平均分应该没有不会的吧。将每位选手第(j)项竞赛的分数加起来,除以选手个数就是第(j)项竞赛的平均分了。

      代码实现:

      for(int i = 0; i < 8; i++){                                            // 算均分 
      	for(int j = 0; j < n; j++) avg[i] += x[j][i];
      	avg[i] /= n;
      }
      
    • 选手 (i) 的总分 (sumx_i = sum_{j=1}^8 x_{ij})

      这也不难理解,将选手每项竞赛的分数加起来就是了。

      代码实现:

      for(int i = 0; i < n; i++) for(int j = 0; j < 8; j++)                  // 算总分 
      	res[i].sumv += x[i][j];
      
    • 选手 (i)(j) 项竞赛的位置分

      [y_{ij}=left{egin{array}{l}{0,left(sum_{j=1}^{N}left|x_{ij}-a v g_{j} ight|=0 ight)} \ {frac{x_{ij}-a v g_{j}}{left(frac{1}{N} sum_{i=1}^{N}left|x_{ij}-a v g_{j} ight| ight.},left(sum_{i=1}^{N}left|x_{ij}-a v g_{j} ight| eq 0 ight)}end{array} ight. ]

      这个有点复杂,首先来弄懂后面括号的内容。

      首先,#define 分差 竞赛得分与均

    分的差

    $sum_{j=1}^{N}left|x_{ij}-a v g_{j}
    ight|$这个式子就是选手$j$的分差之和。
    
    若分差之和为$0$,则选手$i$竞赛$j$位置值为$0$。
    
    若分差之和不为$0$,则位置值取选手$i$竞赛$j$的分差除以选手$i$所有竞赛分差的平均值。
    
    读不懂就仔细多读几遍吧,我写的不好。
    
    代码实现:
    
    ```cpp
    for(int i = 0; i < 8; i++) for(int j = 0; j < n; j++){                 // 算位置分 
    	for(int k = 0; k < n; k++) y[j][i] += abs(x[k][i] - avg[i]);
    	if(y[j][i] != 0) y[j][i] = (x[j][i] - avg[i]) / (y[j][i] / n);
    }
    ```
    
    • 选手 (i) 的总位置分 (sumy_i = sum_{k=1}^3 y_{jk} + 0.8 sum_{k=4}^8 y_{jk})

      也就是说,在总位置分中,前三项竞赛的位置分权值为1,后五项的权值为0.8,求和即可。

      代码实现:

      for(int i = 0; i < n; i++){                                            // 算总位置分 
      	res[i].id = i;
      	res[i].sumv = 0;
      	for(int j = 0; j < 3; j++) res[i].yv += y[i][j];
      	for(int j = 3; j < 8; j++) res[i].yv += 0.8 * y[i][j];
      }
      

      在这里顺便为res数组作初始化

    以上工作做完以后,我们再根据排名规则写一个cmp函数:

    bool cmp(stures r1, stures r2){
    	if(r1.yv != r2.yv) return r1.yv > r2.yv;
    	else if(r1.sumv != r2.sumv) return r1.sumv > r2.sumv;
    	else return r1.id < r2.id;
    }
    

    就是这样,(THE space END)

    (AC space CODE)

    #include<bits/stdc++.h>
    using namespace std;
    struct stures{
    	int id;
    	double yv, sumv;
    }res[1005];
    bool cmp(stures r1, stures r2){
    	if(r1.yv != r2.yv) return r1.yv > r2.yv;
    	else if(r1.sumv != r2.sumv) return r1.sumv > r2.sumv;
    	else return r1.id < r2.id;
    }
    int main(){
    //	freopen("ranking.in", "r", stdin);
    //	freopen("ranking.out", "w", stdout);
    	int n, x[1005][10] = {};
    	double y[1005][10] = {}, avg[10] = {};
    	cin >> n;
    	for(int i = 0; i < n; i++) for(int j = 0; j < 8; j++) cin >> x[i][j];  // 输入 
    	for(int i = 0; i < 8; i++){                                            // 算均分 
    		for(int j = 0; j < n; j++) avg[i] += x[j][i];
    		avg[i] /= n;
    	}
    	for(int i = 0; i < 8; i++) for(int j = 0; j < n; j++){                 // 算位置分 
    		for(int k = 0; k < n; k++) y[j][i] += abs(x[k][i] - avg[i]);
    		if(y[j][i] != 0) y[j][i] = (x[j][i] - avg[i]) / (y[j][i] / n);
    	}
    	for(int i = 0; i < n; i++){                                            // 算总位置分 
    		res[i].id = i;
    		res[i].sumv = 0;
    		for(int j = 0; j < 3; j++) res[i].yv += y[i][j];
    		for(int j = 3; j < 8; j++) res[i].yv += 0.8 * y[i][j];
    	}
    	for(int i = 0; i < n; i++) for(int j = 0; j < 8; j++)                  // 算总分 
    		res[i].sumv += x[i][j];
    	sort(res, res+n, cmp);                                                 // 快排 
    	for(int i = 0; i < n; i++) cout << res[i].id+1 << endl;                // 输出 
    	return 0;
    }
    

    提交记录

    • 用时 89ms
    • 内存 832.00KB

    我这代码效率真的低

    本蒟蒻第一篇题解,管理大大求通过

  • 相关阅读:
    return, break, continue
    equals 与 ==
    过滤器
    通过域名区分虚拟主机
    通过端口区分不同虚拟机
    Nginx实现反向代理
    Nginx安装
    poj2387 Til the Cows Come Home(Dijkstra)
    hdoj2544 最短路(Dijkstra || Floyd || SPFA)
    最小生成树
  • 原文地址:https://www.cnblogs.com/liuxizai/p/13764725.html
Copyright © 2020-2023  润新知