Турнир
Аутор: Андреј Ивашковић
Текст и тест примери: Алекса Милисављевић
Тестирање: Владимир Миленковић
Анализа решења: Андреј Ивашковић
Решење првог подзадатка
Уколико се игра састоји од само једне рунде, то значи да свих својих K жетона користимо у тој рунди. Укупан број поена који можемо да остваримо једнак је броју осталих играча који имају мање од K жетона. Ово решење ради у временској сложености O(M).
Решење другог подзадатка
Довољно је испробати све могуће начине да се K представи као збир N ненегативних целих сабирака, генерисане бектрекингом, и да се за сваку од тих подела одреди број поена који можемо да остваримо. Број начина да се K разбије на N сабирака једнак је N+K-1 \choose N-1, а одређивање броја поена за дату поделу се ради у сложености O(MN). Бектрекинг решење не мора да буде посебно ефикасно да би се у овом подзадатку добили сви поени.
Решење трећег подзадатка
За M=1 постоји само један играч против ког играмо, те је питање како распоредити жетоне да остваримо највећи број победа у рундама. Уколико је у i-тој рунди овај играч поставио a_{i,1} жетона, онда победу у овој рунди остварујемо постављањем a_{i,1}+1 жетона. За остваривање победе у највећем броју рунди, довољно је победити у оним рундама у којима је наш противник ставио најмање жетона. Ово води ка једноставном грамзивом алгоритму: најпре се сортирају рунде по броју жетона саиграча (у растућем поретку), након чега се “буџет” од K жетона троши редом у овим рундама све док нам не остане ниједан жетон. Временска сложеност овог решења је O(N \log N).
Решење четвртог подзадатка
Овај подзадатак се решава применом динамичког програмирања. Дефинишимо тродимензиони низ S_{n,k}, уз 0 \leq n \leq N, 0 \leq k \leq K:
-
S_{n,k}: највећи број поена који се може остварити уколико је искоришћено k жетона у првих n рунди
Тривијално познате вредности у овом низу су:
Нека је [B] индикатор неког логичког израза: 1 уколико B важи и 0 уколико не важи. У случајевима n>0 користимо рекурентну везу:
-
S_{n,k} = \max_{1 \leq z \leq k} (S_{n-1,k-z} + \sum_{j=1}^{m} [a_{n,j} < z]) (*)
Ова рекурентна веза може да се објасни на следећи начин: најбољи начин да се k жетона распореди у n рунди може да се одреди уколико се размотре сви могући бројеви жетона z у n-тој рунди, одреди колико играча има мање од z жетона у n-тој рунди и тако одреди број поена, на то дода оптимална расподела k-z жетона у претходним рундама, и одреди најбоље такво z. Тада је коначан одговор на питање из задатка вредност S_{N,K}, која може да се одреди у временској сложености O(NMK^2).
Решење петог подзадатка
Решење које доноси све поене је оптимизација решења четвртог подзадатка.
Приметимо да су једини значајни бројеви жетона у n-тој рунди 0, a_{n,1}+1, a_{n,2}+1, \ldots, a_{n,M}+1, односно бројеви жетона при којима се остварују различити бројеви поена. У оквиру једне рунде је небитно који играч је ставио колико жетона, битни су само бројеви. Стога не губимо никакве информације сортирањем бројева жетона различитих играча у оквиру једне рунде.
Приметимо и да је S_{n,k} за фиксирано k растуће у n, односно S_{n,k} \leq S_{n',k} за n < n’.
Уз ова два корака, приметимо да није неопходно испитати све могуће z у формули (*). Самим тим рачунање S_{n,k}, које се у претходном подзадатку радило у временској сложености O(MK), може да се уради у O(M). Укупна временска сложеност је O(NMK).
За оне који желе да знају више: овај задатак је инспирисан игром Blotto.