sgu288:Best Tournament Schedule(構造)

題目大意:
       一場比賽有 n  個參賽選手,要求選手之間兩兩都有且僅有一次對決。每一輪中一個選手至多可以對決一次,也就是每一輪選出若干對不相交的選手進行對決。現在要求出最少的對決輪數來結束比賽和此時的對決方案。

分析:
       首先確定答案,當 n  爲偶數的時候,答案爲 n1  ,否則爲 n  ,另外,當 n=1  的時候,答案也爲0 。原因可以自行腦補。
       現在將比賽抽象成一個 n×n  的矩陣GGi,j 表示 i,j  之間的對決發生在第幾輪。那麼我們就是要求每一行每一列不出現重複的數字。
       n  爲奇數爲例,每一行每一列除去 0  就有 n1  個數,我們可以令 Gi,j=(i+j)modans  ,毫無疑問是滿足要求的。
      n 爲偶數的時候,我們需要特殊處理最後一行一列,我們可以令 Gi,n=(i+i)modans  ,那麼此時它也是滿足要求的。

AC code:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define pb push_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof a)
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define per(i, a, b) for(int i = (a); i >= (b); --i)
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;

void open_init()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(0);
}

void close_file()
{
    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
}

const int MAXN = 2009;

int n, ans;
int g[MAXN][MAXN];

int main()
{
    open_init();

    scanf("%d", &n);
    if(n > 1) ans = n-(n&1^1);
    else ans = 0;
    rep(i, 1, ans)
        rep(j, i+1, ans)
            g[i][j] = g[j][i] = (i+j)%ans+1;
    rep(i, ans+1, n)
        rep(j, 1, n-1)
            g[i][j] = g[j][i] = (j<<1)%ans+1;
    printf("%d\n", ans);
    rep(i, 1, n)
    {
        rep(j, 1, n-1)
            printf("%d ", g[i][j]);
        printf("%d\n", g[i][n]);
    }

    close_file();
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章