P17242 [IOI 2026] Tiling Game

· · 题解

IOI 也会有签。

S=TL+TR+BL+BR

将 “L” 按拐点所处的位置分为左上、右上、左下、右下四类。那么可以按照以下策略放置: - 将第一类(左上)放在当前未被填充的 $i+j$ 最小的位置。 - 将第二类(右上)放在当前未被填充的 $i-j$ 最小的位置。 - 将第三类(左下)放在当前未被填充的 $-i+j$ 最小的位置。 - 将第四类(右下)放在当前未被填充的 $-i-j$ 最小的位置。 :::info[为什么该策略是对的] 一个不合法局面的例子: ``` ⬜⬛ ⬛⬛ ⬛⬛ ⬛⬜ ``` 证明我们的策略不可能造成该局面的出现: - 反证法,假设该局面出现。 - 不妨设右侧的 2×2 方块先被填充。 - 由于左侧方块的 $i+j$ 比右侧方块小,故填充第一类 “L” 形时会优先选择左侧方块。 - 与假设矛盾,证毕。 ::: 代码中使用 `set` 来维护。 注意在洛谷上提交时要把 `#include<tiling.h>` 删掉。 ```cpp line-numbers #include<tiling.h> #include<bits/stdc++.h> using namespace std; int n,m; set<pair<int,pair<int,int>>>st[4]; void init(int N,int M){ n=N,m=M; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ st[0].insert({i+j,{i,j}}); st[1].insert({i-j,{i,j}}); st[2].insert({-i+j,{i,j}}); st[3].insert({-i-j,{i,j}}); } } } pair<int,int> receive_block(int TL,int TR,int BL,int BR){ pair<int,int>res; if(!BR) res=(*st[0].begin()).second; else if(!BL) res=(*st[1].begin()).second; else if(!TR) res=(*st[2].begin()).second; else res=(*st[3].begin()).second; auto [i,j]=res; st[0].erase({i+j,{i,j}}); st[1].erase({i-j,{i,j}}); st[2].erase({-i+j,{i,j}}); st[3].erase({-i-j,{i,j}}); return make_pair(i<<1,j<<1); } ```