例題
設有n個運動員要進行網球迴圈賽,設計乙個滿足以下要求的比賽日程表
(1)每個選手必須與其他n-1個選手各賽一次;
(2)每個選手一天只能賽一次;
(3)當n 是偶數,迴圈賽進行n-1簡單天,當n是奇數,迴圈賽進行n天。
分析
1. 首先考慮簡單問題(n = 2^k)
這個我先上乙個圖大家應該就可以明白:
應該很容易想到分治法,有如下規律:對於任意乙個正方形區域(包括4、16……個小方塊)左上角和右下角相等,右上角和左下角相等(如果懶得看漢字就直接看上面幾種顏色的方塊吧)
然後這個**也很容易:
void
settable
(int
**a,
int k)
}//右上角子表就是左下角子表
for(
int row =
0; row < half; row ++)}
//右下角子表就是左上角子表
for(
int row = half; row < len; row ++)}
}}
void
tourna
(int n,
int*
*a)tourna
(n/2
, a)
;copy
(n, a);}
void
copy
(int n,
int*
*a)}
}
2.衍生到一般的偶數(如果n不是2的次方)舉乙個例子(n=6),既然是分治法,按照大的思路,我們把tourna(6, a)問題轉換成tourna(3, a)【這裡的你們就先看成是上面的tourna函式】,那麼問題又來了,n=3怎麼解決呢?(自然引出了奇數的問題,那我們直接考慮下面的奇數問題,這裡大家可以直接跳到第三種情況看,看完之後回看這一點)
我們可以將6分為(1 2 3)和(4 5 6)我們且看兩者單獨考慮的賽程:
考慮到(1 2 3)(4 5 6)「1和4」的第四列(第三天),只有一號選手和四號選手沒比賽,那就讓他們比,同理還有2和5,3和6,推出如下圖【左圖】:
再來分析【右圖】,第一行由於(1 5)(1 6)沒比賽,後面就填他們,對應的也有(5 1)(6 2),再看第二行可以是(2 4)(2 6),由於6在第五天和1比賽了,所以應該是先填(2 6)然後(2 4),對應的也有(6 2)(4 2);後面同理。
【其實我感覺這個就是找規律好嗎,和分治法有「桃子」關係 】
3.n為奇數
考慮到題目中有n天時間比賽,自然想到n = 4 的情況(看下圖)
這個是4個人比賽3天的情況,現在如果只有3個人,那麼豈不是正好是3天,我們僅僅需要將其中的4改變為0(看下圖),代表選手那天空閒就可
其實對於一般的奇數,我們都可以轉換成相應的n + 1,變成偶數再分治求解,最終遞迴到盡頭就是n = 3(然後我們回到第二問)
最終**整理如下
#
include
using
namespace std;
void
output
(int
**a,
int n)
}else
//n為偶數時候的輸出
for(
int i =
0; i < n; i++)}
}void
copy
(int n,
int*
*a)}
}void
copyodd
(int n,
int*
*a)for
(int i =
0; i < m; i ++
)else a[m +i]
[j]= a[i]
[j]+ m;
}for
(int j =
1; j < m; j++
)//填寫右上角和對應的右下角}}
void
makecopy
(int n,
int*
*a)void
tourna
(int n,
int*
*a)if
(n %2==
1)tourna
(n/2
, a)
;//分治
makecopy
(n, a);}
intmain()
多邊形法 解決迴圈賽問題(n分為奇數和偶數)
看到網上關於迴圈賽問題提出過一種多邊形法,感覺這個思路挺簡單的,但是看別人 沒看懂,這裡我簡單分析幾種情況然後寫出自己理解的 這個其實就是每次以某乙個運動員為對稱軸,分割之後對稱的一組比賽,剩下的一輪空也就是和0號組成一對。總結 那麼問題來了,怎樣用 將以上問題描述出來呢,我們可以看到,對於n 5中...
分治法 迴圈賽日程安排問題
問題 描寫敘述 設有n 2 k 位選手參加網球迴圈賽,迴圈賽共進行n 1 天,每位選手要與其它 n 1位選手比賽一場。且每位選手每天僅僅能賽一場,試安排比賽。舉例說明 1,當 n為偶數時,迴圈賽一共要進行n 1 天 比方,有運動員 周董,信哥,蔡依林,小七。一共 4個人,能夠例如以下安排 運動員第一...
分治法 迴圈賽日程表問題
迴圈賽日程表問題問題描述 設有n n 2 k 位選手參加網球迴圈賽,迴圈賽共進行n 1天,每位選手要與其他n 1位選手比賽一場,且每位選手每天必須比賽一場,不能輪空。試按此要求為比賽安排日程 1 每個選手必須與其他n 1個選手各賽一場 2 每個選手一天只能賽一場 3 迴圈賽一共進行n 1天。思路和 ...