【编程题目】n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,

36.引用自网友:longzuo(运算)
谷歌笔试:
19
n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,
存储在一个二维数组 w[n][n]中,w[i][j] 的值代表编号为 i,j 的队伍中更强的一支。
所以 w[i][j]=i 或者 j,现在给出它们的出场顺序,并存储在数组 order[n]中,
比如 order[n] = {4,3,5,8,1......},那么第一轮比赛就是 4 对 3, 5 对 8。.......
胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,
下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是 4 对 5,直至出现第一名
编程实现,给出二维数组 w,一维数组 order 和 用于输出比赛名次的数组 result[n],
求出 result。

我用result先存储每个队伍晋级的轮次,利用vector后进先出的特点来输出结果

/*
36.引用自网友:longzuo(运算)
谷歌笔试:
19
n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,
存储在一个二维数组 w[n][n]中,w[i][j]  的值代表编号为 i,j 的队伍中更强的一支。
所以 w[i][j]=i  或者 j,现在给出它们的出场顺序,并存储在数组 order[n]中,
比如 order[n] = {4,3,5,8,1......},那么第一轮比赛就是 4 对 3,  5 对 8。.......
胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,
下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是 4 对 5,直至出现第一名
编程实现,给出二维数组 w,一维数组 order  和  用于输出比赛名次的数组 result[n],
求出 result。
*/
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;

//假设n一定是2的n次方,即每一轮不会出现轮空的情况
void getRank(int *w[], int * order, int * result, int n)
{
    memset(result, 0, n * sizeof(int));
    vector<int> stack;
    int round = 0;
    int n2 = n;
    while(n2 != 1)
    {
        n2 = (n2>>1);
        round++;
    }
    for(int r = 0; r < round; r++) //对比赛轮次循环
    {
        int i = 0;
        int num = 0;
        int member[2] = {0};
        while(i < n)//对比赛队伍循环
        {
            if(result[i] == r)
            {
                member[num++] = i;
            }
            if(num == 2)
            {
                if(*((int*)w + n * member[0] + member[1]) == member[0])
                {
                    result[member[0]]++;
                    stack.push_back(member[1]);
                }
                else
                {
                    result[member[1]]++;
                    stack.push_back(member[0]);
                }
                num = 0;
            }
            i++;
        }
    }

    for(int i = 0; i < n; i++) //冠军进栈
    {
        if(result[i] == round)
        {
            stack.push_back(i);
        }
    }

    for(int i = 0; i < n; i++)
    {
        result[i] = stack.back();
        stack.pop_back();
    }
}

int main()
{
    int w[4][4] = {{0, 0, 2, 0},
                   {0, 1, 1, 3},
                   {2, 1, 2, 3},
                   {0, 3, 3, 3}};
    int order[4] ={1, 2, 3, 4};
    int result[4];
    getRank((int **)w, order, (int *)result, 4);
    return 0;
}

我的实现不好,因为没有考虑轮空的情况。网上有两个我觉得还不错的方法,都考虑了轮空,也很简洁。

http://blog.csdn.net/yuucyf/article/details/6733226

利用了vector 的 earse  每次存名次的时候从 result的最后一个开始存就可以了。

/*----------------------------
Copyright by yuucyf. 2011.08.30
-----------------------------*/
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;

bool CalcPosition(int **ppW, int *pOrder, int *pResult, int nGroup)    //nGroup arg mean n x n
{
    assert(ppW);
    assert(pOrder);
    assert(pResult);
    assert(nGroup > 0);

    int i32I = 0, i32J = 0;
    int nCurPos = nGroup - 1;
    vector<int> vectOrder;
    for (i32I = 0; i32I < nGroup; i32I++)
        vectOrder.push_back(pOrder[i32I]);

    while (vectOrder.size() > 1)
    {
        for (vector<int>::iterator it = vectOrder.begin(); it != vectOrder.end(); ++it)
        {
            if (it + 1 != vectOrder.end())
            {
                if (ppW[*it][*(it+1)] == *it)
                {
                    pResult[nCurPos--] = *(it+1);
                    vectOrder.erase(it+1);
                }
                else
                {
                    pResult[nCurPos--] = *it;
                    it = vectOrder.erase(it);
                }
            }
        }
    }

    if (vectOrder.size() == 1)
        pResult[nCurPos--] = vectOrder[0];

    return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
    int n;
    cout << "请输入队伍数";
    cin >> n;
    cout << endl << "输入实力对比关系" << endl;

    int **ppW = new int* [n];
    assert(*ppW);
    for (int i32I = 0; i32I < n; i32I++)
    {
        ppW[i32I] = new int [n];
        assert(ppW);
        for (int i32J = 0; i32J < n; i32J++)
            cin >> ppW[i32I][i32J];
    }

    int *pOrder = new int[n];
    assert(pOrder);
    cout << "请输入出场顺序" << endl;
    for (int i32I = 0; i32I < n; i32I++)
        cin >> pOrder[i32I];

    int *pRes = new int[n];
    assert(pRes);
    if (CalcPosition(ppW, pOrder, pRes, n))
    {
        cout << endl << "比赛名次为:(大到小)" << endl;
        for (int i32I = 0; i32I < n; i32I++)
            cout << pRes[i32I] << " ";
    }

    //don‘t forget to free memory...

    return 0;
}

http://www.tuicool.com/articles/jq2INv

用变量i k的跳跃实现每一轮的队伍选取。 二维指针传参的地方可以改进。

#include<iostream>

using namespace std;

#define N 5
void GetResult(int (*w)[N], int* order, int* result)
{
  int i = 0;
  int k = 1;
  int j = N -1;
  while(1)
  {
    i = 0;
    if(i + k > N -1)
    {
      result[j] = order[0];
      break;
    }

    while(i + k <= N-1)
    {
      int ii = order[i];

      int jj = order[i+k];
      if(w[ii][jj] == ii)
        result[j--] = jj;
      else
      {
        result[j] = ii;
        order[i]= order[i+k];
        order[i+k] = result[j];
        j --;
      }
      i = i + 2*k;
    }
    k *= 2;
  }
}

int main()
{
  int a[5][5] = {{0,1,2,3,4},{1,1,2,3,4},{2,2,2,3,4},{3,3,3,3,4},{4,4,4,4,4}};
  int order[5] = {4,3,1,2,0};
  int result[5];
  GetResult(a, order, result);

  int i = 0;
  cout << "result order: ";
  while(i < 5)
  {
    cout << result[i++] << ",";
  }
  cout << endl;
}

【编程题目】n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,

时间: 2024-11-10 13:37:49

【编程题目】n 支队伍比赛,分别编号为 0,1,2。。。。n-1,已知它们之间的实力对比关系,的相关文章

编程题:指向二维数组元素的指针变量。功能:已知二维数组a[2][3],输入输出全部元素。

#include<stdio.h> void main() { int a[2][3],i,j; int *p; /*用坐标法输入二维数组元素*/ for(i=0;i<2;i++) for(j=0;j<3;j++) scanf("%d",&a[i][j]); /*用指针法输出二维数组元素*/ p=a[0];         /*等价于p&a[0][0];*/ for(;p<a[0]+6;p++)   printf("%4d&quo

【目录】编程题目

编程题目 如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1) 一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数.☆ 请修改 append 函数,利用这个函数实现两个非降序链表的并集 一串首尾相连的珠子(m 个),有 N 种颜色(N<=10),取出其中一段,要求包含所有 N 中颜色,并使长度最短. 求一个有向连通图的割点,割点的定义是,如果除去此节点和与其相关的边, 有向图不再连通 有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前

【编程题目】n 个骰子的点数

67.俩个闲玩娱乐(运算).2.n 个骰子的点数.把 n 个骰子扔在地上,所有骰子朝上一面的点数之和为 S.输入 n,打印出 S 的所有可能的值出现的概率. 思路:用递归把每个骰子的可能情况变量,记录各种和S出现的次数 比上 总情况数就是概率 /* 67.俩个闲玩娱乐(运算). 2.n 个骰子的点数. 把 n 个骰子扔在地上,所有骰子朝上一面的点数之和为 S.输入 n, 打印出 S 的所有可能的值出现的概率. */ #include <stdio.h> #include <stdlib.

【编程题目】有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序;(需要回头仔细研究)

32.(数组.规划)有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序:要求:通过交换 a,b 中的元素,使[序列 a 元素的和]与[序列 b 元素的和]之间的差最小.例如: var a=[100,99,98,1,2,3];var b=[1,2,3,4,5,40]; 首先,目标一定是先找到n个数字,使得数字和比总和的一半小,但是最接近. 思路一:开始看这道题跟之前学的动态规划很像,就想用动态规划来解.但是....做不出来........... 必须要选一半的数字让我头都大了. 思路二:

【编程题目】判断整数序列是不是二元查找树的后序遍历结果,如果是,构建该二元查找树

判断整数序列是不是二元查找树的后序遍历结果题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回 true,否则返回 false.例如输入 5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回 true.如果输入 7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false. 做这个题目的时候最开始傻了,想着从前到后根据数字的大小关系判断.后来幡然醒悟,根据后序遍历的特点.序列最后一

【编程题目】扑克牌的顺子

67.俩个闲玩娱乐(运算).1.扑克牌的顺子从扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这 5 张牌是不是连续的.2-10 为数字本身,A 为 1,J 为 11,Q 为 12,K 为 13,而大小王可以看成任意数字. 思路: 用min.max记录输入的牌对应的数字大小,不考虑王,用wnum记录王的个数, record[13]记录每种牌是否出现过.设要判断n个牌是否连续 只要  出现不重复 且(max - min + 1) 在 [ n - wnum , n ]之间即可 /* 67.俩个闲玩娱

火车调度-c#求解-英雄会在线编程题目

题目: 火车调度 返回首页 发布公司: 有 效 期: 赛 区: CSDN 2014-04-30至2015-04-30 北京 难 度 等 级: 答 题 时 长: 编程语言要求: 120分钟 C C++ Java C# 题目详情 火车从A地和B地之间运行,你知道火车从某地出发的时间和到达某地的时间(这个时间出发,一定这个时候到达).火车到达目的地后,不能立刻返回,需要经过t分钟检修才可以返回.列车只在A.B两地运行.你知道每天内的时刻表,求A,B两地各需要存放多少辆列车,才能满足这个时刻表?即只要该

另类编辑距离-c#求解-英雄会在线编程题目

Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果我们要把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢? 一. 生成对象的原始模式 假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性. var C

【编程题目】颠倒栈☆

66.颠倒栈(栈).题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1 在栈顶.颠倒之后的栈为{5, 4, 3, 2, 1},5 处在栈顶. 思路:我自己没做出来,因为总觉得用不上递归.看了网上答案http://blog.csdn.net/cxllyg/article/details/7655935 根据里面的思路 自己照着写了一遍 /* 66.颠倒栈(栈). 题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1 在栈顶. 颠倒之后的栈为{5, 4, 3, 2,