题目: 牛客网链接
概述: 给了每个国家的金牌数,奖牌数,人口数。然后给出四种排序条件,奖牌总数,金牌总数,金牌人口比例,奖牌人口比例。找出给定国家的最优排序方法。
思路: 用了两种方法来解决这个问题。一个是用一个二维数组,还有一个是面向对象的方法。 这一题数据集比较坑,有时候人口总数竟然会为0。
方法一:面向对象法
vector存储对象时候很巧妙 ,多复习。
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
class Country
{
public:
int gold;
int medal;
int plt;
double perGold;
double perMedal;
int best;
int method;
Country(int gold, int medal, int plt)
{
this -> gold = gold;
this -> medal = medal;
this -> plt = plt;
perGold = (double)gold / plt;
if (gold == 0 && plt == 0) //这里解释一下,因为测试用例有毛病,会有人口零,奖牌零的情况出现
perGold = 0; //而如果除数被除数都是0,那么结果是NAN——Not A Number
perMedal = (double)medal / plt; //而经过调试发现,调用sort的时候,sort会把vector以NAN为分界
if (medal == 0 && plt == 0)
perMedal = 0; //分开来,然后各自进行排序,然后就出错了
best = 100000;
method = 100000;
}
};
bool more(Country* c1, Country* c2, int flag)
{
switch(flag)
{
case 1: return c1->gold > c2->gold; break;
case 2: return c1->medal > c2->medal; break;
case 3: return c1->perGold > c2->perGold; break;
case 4: return c1->perMedal > c2->perMedal; break;
drfault: break;
}
return false;
}
bool cmp1(Country* c1, Country* c2)
{
return c1->gold > c2->gold;
}
bool cmp2(Country* c1, Country* c2)
{
return c1->medal > c2->medal;
}
bool cmp3(Country* c1, Country* c2)
{
return c1->perGold > c2->perGold;
}
bool cmp4(Country* c1, Country* c2)
{
return c1->perMedal > c2->perMedal;
}
void selectSort(vector<Country*> staySort, int flag)
{
int length = staySort.size();
vector<Country*> temp;
for(int i = 0; i < length; i++)
{
temp.push_back(staySort[i]);
}
switch(flag)
{
case 1: sort(temp.begin(), temp.end(), cmp1); break;
case 2: sort(temp.begin(), temp.end(), cmp2); break;
case 3: sort(temp.begin(), temp.end(), cmp3); break;
case 4: sort(temp.begin(), temp.end(), cmp4); break;
drfault: break;
}
int best = 1;
if(temp[0]->best > best || (temp[0]->best == best && temp[0]->method > flag)){
temp[0]->best = best;
temp[0]->method = flag;
}
for(int i = 1; i < length; i++)
{
if(more(temp[i - 1], temp[i], flag))
{
best = i + 1;
}
if(temp[i]->best > best || (temp[i]->best == best && temp[i]->method > flag))
{
temp[i]->best = best;
temp[i]->method = flag;
}
}
}
int main()
{
int m, n;
while(scanf("%d%d", &n, &m) != EOF)
{
vector<Country*> countries, staySort;
for(int i = 0; i < n; i++)
{
int gold, medal, plt;
scanf("%d%d%d", &gold, &medal, &plt);
countries.push_back(new Country(gold, medal, plt));
}
for(int i = 0; i < m; i++)
{
int index;
scanf("%d", &index);
staySort.push_back(countries[index]);
}
selectSort(staySort, 1);
selectSort(staySort, 2);
selectSort(staySort, 3);
selectSort(staySort, 4);
for(int i = 0; i < m; i++)
{
printf("%d:%d\n", staySort[i] -> best, staySort[i] -> method);
}
printf("\n");
}
return 0;
}
方法二:二维数组法
二维数组的操作是个终点,我们采用iterator进行操作,在代码中划了重点。另外整体的思路也很重要。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//用于sort函数
bool cmp(double a, double b)
{
return a > b;
}
//采用二维数组来进行存储,第一行是金牌总数,第二行是奖牌总数,第三行是金牌/人口,第四行是奖牌/人口
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
vector<vector<double> > country(4, vector<double>(n));
for(int i = 0; i < n; i++)
{
int gold, medal, plt;
double perGold, perMedal;
scanf("%d%d%d", &gold, &medal, &plt);
//因为数据集中给出的人口,有时候为0,所以考虑被除数为0的情况
perGold = (double)gold / plt;
if (gold == 0 && plt == 0) //这里解释一下,因为测试用例有毛病,会有人口零,奖牌零的情况出现
perGold = 0; //而如果除数被除数都是0,那么结果是NAN——Not A Number
perMedal = (double)medal / plt; //而经过调试发现,调用sort的时候,sort会把vector以NAN为分界
if (medal == 0 && plt == 0) //分开来,然后各自进行排序,然后就出错了
perMedal = 0;
country[0][i] = gold;
country[1][i] = medal;
country[2][i] = perGold;
country[3][i] = perMedal;
}
//用来存储用来比较的m个
vector<vector<double> > ctryToCmp(4, vector<double>(m));
for(int i = 0; i < m; i++)
{
//输入m个下标
int index;
scanf("%d", &index);
ctryToCmp[0][i] = country[0][index];
ctryToCmp[1][i] = country[1][index];
ctryToCmp[2][i] = country[2][index];
ctryToCmp[3][i] = country[3][index];
}
//这里是二维数组操作的一个重点
for(vector<vector<double> > :: iterator it = country.begin(); it != country.end(); it++)
{
sort(it -> begin(), it -> end(), cmp);
}
//这里开始对这m个选出来要排序的数找他们的排名和最适合他们的排名方式
for(int i = 0; i < m; i++)
{
int best = n, method = 1;
//分别对应着四中情况
for(int j = 0; j < 4; j++)
{
//与没排序前的m个一一对比,这样就可以按照顺序输出这m个国家的情况 。
for(int k = 0; k < n; k++)
{
if(country[j][k] == ctryToCmp[j][i] && best > k + 1)
{
best = k + 1;
method = j + 1;
break;
}
}
//如果是第一名就不用再进行比较了
if(best == 1)
{
break;
}
}
printf("%d:%d\n", best, method);
}
printf("\n");
}
return 0;
}