洛谷P1309瑞士轮解析

最近看到一场比赛,机制是真

于是我就去洛谷看看,发现还有瑞士轮这个好东西(题目链接:P1309 [NOIP2011 普及组] 瑞士轮 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

但我看了看题解

我全不会

于是我寻思着,自己去做,发现弄来弄去是结构体和排序(sort真香)

因为我太懒了要节省时间,so,万能开头再定义结构

#include <bits/stdc++.h>
using namespace std;
struct xuanshou//创造一个结构体
{
  int bianhao;//编号
  int shili;//实力
  int fengshu;//分数
} a[200020],win[200020],lose[200020];

接下来,就是主函数了

思路:输入——判定——合并——输出

那么第一步就是输入

int n,r,q;//n代表选手,r代表轮数,q代表要求的人第q名
  cin>>n>>r>>q;
  n=n*2;//代表总共有2*n名选手
  for(int i=1; i<=n; i++)
  {
    a[i].bianhao=i;//输入编号
    cin>>a[i].fengshu;//输入初始分数
  }
  for(int i=1; i<=n; i++)
  {
    cin>>a[i].shili;//输入实力
  }

当然,如果要判定,就得请我们的sort来整理(虽然时间会炸,但我也没想到什么其他的了)

sort(a+1,a+n+1,cmp);//首先进行初始排序

靠,忘了定义cmp规则了  接下来我们来制定排序规则

题目说了,如若实力相等,那么看编号,也就说明不存在平局的观念,你看,思路就出来了,先判断编号在判断实力,即

bool cmp(xuanshou a,xuanshou b)//排序顺序
{
  //先按照分数从大到小排序
  if(a.fengshu==b.fengshu)//如果分数相同则按照编号从大到小排序
    return a.bianhao<b.bianhao;//判断其编号,如若成立,执行下一步
  else
    return a.fengshu>b.fengshu;//判断分数
}

好,那么好,这样就可以开始下一步了,判定!!!

由于瑞士轮是多重赛,所以我们就可以用双循环来解决

当然,因为其要判断输赢,所以可以用下标解决(就是0,1,不懂去看:详解数组的下标_数组下标-CSDN博客

那么过程就出来了

循环——判定实力——计算和计入输赢——结算——输出,即

for(int i=1; i<=r; i++)
  {
    int win1=1,lose1=1;//定义win数组和lose数组的下标
    for(int j=1; j<=n; j=j+2)
      if(a[j].shili>a[j+1].shili)	//判断第一位选手实力是否大于第二位
      {
        //a[j]赢了,a[j+1]输了
        a[j].fengshu++;			//分数加一
        win[win1]=a[j];			//放到win数组里
        win1++;					//下标加一,为了方便存储最后一名选手
        lose[lose1]=a[j+1];		//输了放在lose数组中
        lose1++;				//下标加一,为了方便存储最后一名选手
      }
      else//如果第二位反杀了第一位
      {
        a[j+1].fengshu++;		//逻辑同上
        win[win1]=a[j+1];
        win1++;
        lose[lose1]=a[j];
        lose1++;
      }
    merge(win+1,win+win1,lose+1,lose+lose1,a+1,cmp);
  }//重新合并到a数组中,为了确保下一轮重新从a数组中进行分配

好了,最后万事具备,只欠东风,把输出一点,AC拿到手软,完整程序如下

#include <bits/stdc++.h>
using namespace std;
struct xuanshou//创造一个结构体
{
  int bianhao;//编号
  int shili;//实力
  int fengshu;//分数
} a[200020],win[200020],lose[200020];
bool cmp(xuanshou a,xuanshou b)//排序顺序
{
  //先按照分数从大到小排序
  if(a.fengshu==b.fengshu)//如果分数相同则按照编号从大到小排序
    return a.bianhao<b.bianhao;//判断其编号,如若成立,执行下一步
  else
    return a.fengshu>b.fengshu;//判断分数
}
int main()
{
  int n,r,q;//n代表选手,r代表轮数,q代表要求的人第q名
  cin>>n>>r>>q;
  n=n*2;//代表总共有2*n名选手
  for(int i=1; i<=n; i++)
  {
    a[i].bianhao=i;//输入编号
    cin>>a[i].fengshu;//输入初始分数
  }
  for(int i=1; i<=n; i++)
  {
    cin>>a[i].shili;//输入实力
  }
  sort(a+1,a+n+1,cmp);//首先进行初始排序
  for(int i=1; i<=r; i++)
  {
    int win1=1,lose1=1;//定义win数组和lose数组的下标
    for(int j=1; j<=n; j=j+2)
      if(a[j].shili>a[j+1].shili)	//判断第一位选手实力是否大于第二位
      {
        //a[j]赢了,a[j+1]输了
        a[j].fengshu++;			//分数加一
        win[win1]=a[j];			//放到win数组里
        win1++;					//下标加一,为了方便存储最后一名选手
        lose[lose1]=a[j+1];		//输了放在lose数组中
        lose1++;				//下标加一,为了方便存储最后一名选手
      }
      else//如果第二位反杀了第一位
      {
        a[j+1].fengshu++;		//逻辑同上
        win[win1]=a[j+1];
        win1++;
        lose[lose1]=a[j];
        lose1++;
      }
    merge(win+1,win+win1,lose+1,lose+lose1,a+1,cmp);
  }//重新合并到a数组中,为了确保下一轮重新从a数组中进行分配
  cout<<a[q].bianhao;//求第q名选手的编号
  return 0;//大功告成 
}

你还在看什么?写题目去啊!

(初二菜鸡第一次制作,大佬喷轻点)

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值