1. 程式人生 > >分治演算法:乒乓球比賽的日程安排

分治演算法:乒乓球比賽的日程安排

乒乓球比賽的日程安排

問題:

設有n位選手參賽,初賽進行n-1天,每位選手每天必須比賽一次,不能輪空。程式設計求解賽程安排。

分析:

1、求n位選手的賽程安排,可採用分治演算法的思想,將問題規模不斷縮小,比如縮小到8,4,2等規模大小;

2、分析2,4,8等小規模時的賽程安排:


分治演算法主要思想:

(1)、若原問題規模大小不便計算,將問題原本規模分解成若干個規模較小的相同問題;

(2)、每個子問題求解相互獨立,且與原問題形式相同,遞迴解這些子問題合併後組成原問題答案;

分治演算法適用問題:

(1)、問題可分解成若干個規模較小的相同問題;

(2)、合併子問題的解可以得到原問題的解;

(3)、各個子問題相互獨立;

分治演算法的主要步驟:

(1)、分解:縮小問題規模;

(2)、求解:足夠小的規模可用簡單方法求解;

(3)、合併:按照求解問題要求,合併子問題的解,構成最終的解;

程式碼實現:

#include <iostream>
#define max 64
int a[max+1][max+1] = {0};
void game_cal(int k, int n)
{
    if (n == 2)
    {
        a[k][1] = k;
        a[k][2] = k + 1;
        a[k+1][1] = k+1;
        a[k+1][2] = k;
    }
    else
    {
        game_cal(k, n/2);
        game_cal(k+n/2, n/2);
        for (int i = k; i < k+n/2; ++i)
        {
            for (int j = n/2+1; j <= n; ++j)
                a[i][j] = a[i+n/2][j-n/2];
        }
        for (int i = k+n/2; i < k+n; ++i)
        {
            for (int j = n/2+1; j <= n; ++j)
                a[i][j] = a[i-n/2][j-n/2];
        }
    }
}
int main()
{
    int num;
    std::cout << "enter the player numbers:" << std::endl;
    std::cin >> num;
    game_cal(1, num);
    std::cout << " n ";
    for (int i = 1; i < num; ++i)
        std::cout << i << " ";
    std::cout <<std::endl;
    for (int i = 1; i <= num; ++i)
    {
        for (int j = 1; j <=num; ++j)
            printf("%2d", a[i][j]);
        std::cout << std::endl;
    }
    return 0;
}

答案截圖:


缺陷:

只能解決2的整數次冪資料輸入;

資料大小限制,不過可以在程式碼頭部,巨集定義部分修改;

*****

分治和遞迴的區別與聯絡:

遞迴:函式直接或者間接的呼叫自身;

遞迴是分治演算法在解決問題時可能用到的方法(當問題規模足夠簡單時直接計算即可);