Foul Play UVA - 1609

本文介绍了一种算法,用于设计确保特定队伍(编号1)在淘汰赛中获胜的比赛方案。该算法利用了两个关键条件:1号队伍至少能击败一半对手,及间接胜出的可能性。通过三个阶段(消灭不可胜对手、寻找可胜对手、匹配剩余对手)实现目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门

题意:有n只队伍(n是2的整数幂)打淘汰赛,每一轮都是两两配对,胜利者进入下一轮。每一只队伍的实力都是确定的,你最喜欢编号为一的队伍,设计一个方案让队伍一一定胜利。

思路:这个题目有两个关键性的条件
条件1:1号队伍至少能打败一半的队伍。
条件2:对于不能直接打败的队伍t,存在能够打败的队伍t1,t1能够打败t。
这两个条件是至关重要的,设计三个阶段
阶段1:尽可能的消灭队伍1无法打败的队伍
阶段2:在还没匹配的队伍中找到一个1号队伍能够打败的
阶段3:将剩余的队伍进行匹配

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define MAXN 1100
#define MAXE 210
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define pi acos(-1.0)

using namespace std;

char str[MAXN][MAXN];
vector<int> win;
vector<int> lose;

int main() {
  std::ios::sync_with_stdio(false);
  int n;
  while (~scanf("%d", &n)) {
    for (int i = 1; i <= n; ++i) {
      scanf("%s", str[i] + 1);
    }
    win.clear();
    lose.clear();
    for (int i = 2; i <= n; ++i) {
      if (str[1][i] == '1') {
        win.push_back(i);
      } else {
        lose.push_back(i);
      }
    }
    int m = n;
    while (m >>= 1) {
      vector<int> win2, lose2, final2;
      for (int i = 0; i < lose.size(); ++i) {
        bool flag = false;
        for (int j = 0; j < win.size(); ++j) {
          if (win[j] != -1 && str[win[j]][lose[i]] == '1') {
            printf("%d %d\n", win[j], lose[i]);
            win2.push_back(win[j]);
            win[j] = -1;
            flag = true;
            break;
          }
        }
        if (!flag) {
          final2.push_back(lose[i]);
        }
      }
      bool flag = false;
      for (int i = 0; i < win.size(); ++i) {
        if (win[i] != -1 && !flag) {
          flag = true;
          printf("1 %d\n", win[i]);
          win[i] = -1;
        } else if (win[i] != -1 && flag) {
          final2.push_back(win[i]);
        }
      }
      for (int i = 0; i < final2.size(); i += 2) {
        printf("%d %d\n", final2[i], final2[i + 1]);
        if (str[final2[i]][final2[i + 1]] == '1') {
          if (str[1][final2[i]] == '1') {
            win2.push_back(final2[i]);
          } else {
            lose2.push_back(final2[i]);
          }
        } else {
          if (str[1][final2[i + 1]] == '1') {
            win2.push_back(final2[i + 1]);
          } else {
            lose2.push_back(final2[i + 1]);
          }
        }
      }
      win = win2;
      lose = lose2;
    }
  }
  return 0;
}

/*
4
0110
0011
0000
1010
8
00111010
10101111
00010010
01000101
00110010
10101011
00010000
10101010
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值