【uoj#225】[UR #15]奥林匹克五子棋 构造
題目描述
兩個人在 $n\times m$ 的棋盤上下 $k$ 子棋,問:是否存在一種平局的情況?如果存在則輸出一種可能的最終情況。
輸入
第一行三個正整數 $n,m,k$ ,意義如前所述。
輸出
如果雙方不能打成平局,輸出 $?1$ ;
否則輸出 $n×m$ 行,第 $i$ 行兩個整數 $x_i,y_i$ 表示第 $i$ 次落子的坐標為第 $x_i$ 行第 $y_i$ 列。黑子先行,所以 $i$ 為奇數時為黑方落子,$i$ 為偶數時白方落子。坐標需滿足 $1≤x_i≤n,1≤y_i≤m$ 。
樣例輸入
4 4 3
樣例輸出
1 2
1 1
1 4
1 3
2 1
2 3
2 2
2 4
3 3
3 2
3 4
3 1
4 1
4 4
4 3
4 2
題解
構造
顯然 $k=1$ 時無解。
$k=2$ 當且僅當 $\text{min}(n,m)=1$ 時有解。因為若 $n>1,m>1$ ,對于一個 $2\times 2$ 的部分一定無法避免兩個連續。
當 $k\ge 3$ 時,可以構造出如下的棋盤:
顯然這其中包含連續的棋子數最多只有 $2$ 。
那么是否滿足O與X相差不超過1呢?
容易發現只有 $n\mod 4=2$ (此時第一列會多填兩個O)且 $m$ 為奇數時不成立,這種情況下把棋盤向上平移一排(即第一列從上至下是OXXOOXXOO...XXOOX)即可。
時間復雜度 $O(nm)$
#include <cstdio> int ax[125010] , ay[125010] , at , bx[125010] , by[125010] , bt; int main() {int n , m , k , i , j;scanf("%d%d%d" , &n , &m , &k);if(k == 1) puts("-1");else if(k == 2){if(n > 1 && m > 1) puts("-1");elsefor(i = 1 ; i <= n ; i ++ )for(j = 1 ; j <= m ; j ++ )printf("%d %d\n" , i , j);}else{if((n & 3) == 2 && m & 1){for(i = 1 ; i <= n ; i ++ ){for(j = 1 ; j <= m ; j ++ ){if(((i & 3) > 1) == (j & 1)) ax[++at] = i , ay[at] = j;else bx[++bt] = i , by[bt] = j;}}}else{for(i = 1 ; i <= n ; i ++ ){for(j = 1 ; j <= m ; j ++ ){if(((i & 3) && ((i & 3) < 3)) == (j & 1)) ax[++at] = i , ay[at] = j;else bx[++bt] = i , by[bt] = j;}}}for(i = 1 ; i <= n * m ; i ++ ){if(i & 1) printf("%d %d\n" , ax[at] , ay[at]) , at -- ;else printf("%d %d\n" , bx[bt] , by[bt]) , bt -- ;}}return 0; }?
轉載于:https://www.cnblogs.com/GXZlegend/p/8191363.html
總結
以上是生活随笔為你收集整理的【uoj#225】[UR #15]奥林匹克五子棋 构造的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IE和DOM事件流、普通事件和绑定事件的
- 下一篇: Python爬虫:Xpath语法笔记