cf1551 D2. Domino (hard version)
作者:互联网
题意:
给定空的 n×m 棋盘,用 1×2 横骨牌和 2×1 竖骨牌放满棋盘。要求不能重叠且横骨牌的数量恰为 k。
输入 n,m,k。n,m <= 100
思路:
n m 不能都为奇数。
若 n 为偶数:先考虑第一列,第一列中被竖骨牌占据的格子数必为偶数,剩下的偶数个格子要放偶数个横骨牌,因此会向第二列 “伸出” 偶数个骨牌。第二列中有偶数个格子被竖骨牌占据,偶数个格子被第一列伸过来的横骨牌占据,另有偶数个空格子需要放横骨牌。
以此类推,发现横骨牌的数量即 k 必须为偶数。(当然横骨牌不能太多,否则放不下,故还应要求 k <= n×(m/2)
若 n 为奇数,则 m 为偶数:还是先考虑第一列,第一列中被竖骨牌占据的格子数必为偶数,剩下的奇数个格子要放奇数个横骨牌,因此会向第二列 “伸出” 奇数个骨牌。第二列中有偶数个格子被竖骨牌占据,奇数个格子被第一列伸过来的横骨牌占据,另有偶数个空格子需要放横骨牌。
事实上,第 1,3,5,... 列都必须向下一列 “伸出” 奇数个(即至少一个)横骨牌。那就不妨在一开始先把一行放满,转化为 n 为偶数的情形。
const signed N = 3 + 100;
char g[N][N];
void paint(int x1, int y1, int x2, int y2) { //涂色,不能与周围相同
char c = 'a';
while(g[x1-1][y1]==c||g[x1+1][y1]==c||g[x1][y1-1]==c||
g[x1][y1+1]==c||g[x2-1][y2]==c||g[x2+1][y2]==c||
g[x2][y2-1]==c||g[x2][y2+1]==c) c++;
g[x1][y1] = g[x2][y2] = c;
}
bool work(int n, int m, int k) { //构造答案
if(n % 2) { //n为奇数
if(m % 2 || k < m/2 || !work(n-1,m,k-m/2)) return 0;//m为奇或者横骨牌太少
for(int i = 1; i <= m; i += 2) paint(n,i,n,i+1);//放满最后一行
return 1;
}
if(k % 2 || k > n*(m/2)) return 0; //特判一下无解情况
for(int j = 1; j <= m; j += 2) //每次涂2*2格
for(int i = 1; i <= n; i += 2)
if(k) paint(i,j,i,j+1), paint(i+1,j,i+1,j+1), k -= 2;
else paint(i,j,i+1,j), paint(i,j+1,i+1,j+1);
return 1;
}
void sol() {
int n, m, k; cin >> n >> m >> k;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
g[i][j] = 0;
if(!work(n,m,k)) return cout << "NO" << endl, void();
cout << "YES" << endl;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++)
cout << g[i][j];
cout << endl;
}
}
标签:格子,奇数,int,Domino,hard,偶数,骨牌,y2,D2 来源: https://www.cnblogs.com/wushansinger/p/16343678.html