数据弱,直接搜
暴力版:
#include <cstdio>
char mat[8][8];
int mmap[5] = {0, 1, 1, 3, 3};
bool check(int r, int c)
{
// row
for(int j = 1; j <= 4; j++)
if(j != c && mat[r][c] == mat[r][j]) return false;
// column
for(int i = 1; i <= 4; i++)
if(i != r && mat[r][c] == mat[i][c]) return false;
// block
int nr = mmap[r], nc = mmap[c];
for(int i = nr; i < nr + 2; i++)
for(int j = nc; j < nc + 2; j++)
if((i != r || j != c) && mat[r][c] == mat[i][j]) return false;
return true;
}
int num;
int pr[20], pc[20];
bool dfs(int k)
{
if(k == num) return true;
int r = pr[k], c = pc[k];
for(int i = 1; i <= 4; i++)
{
mat[r][c] = '0' + i;
if(!check(r, c)) {mat[r][c] = '*'; continue;}
if(dfs(k + 1)) return true;
mat[r][c] = '*';
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ca++)
{
for(int i = 1; i <= 4; i++)
scanf("%s", mat[i] + 1);
num = 0;
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= 4; j++)
if(mat[i][j] == '*')
{pr[num] = i; pc[num] = j; num++;}
dfs(0);
printf("Case #%d:\n", ca);
for(int i = 1; i <= 4; i++)
printf("%s\n", mat[i] + 1);
}
return 0;
}
状压版:
#include <cstdio>
#include <cstring>
int r[5], c[5], block[5];
int mr[4] = {1, 1, 3, 3};
int mc[4] = {1, 3, 1, 3};
char mat[8][8];
int num;
int pr[20], pc[20];
int f(int nr, int nc)
{
if(nr <= 2)
{
if(nc <= 2) return 0;
else return 1;
}
else
{
if(nc <= 2) return 2;
else return 3;
}
}
bool dfs(int k)
{
if(k == num) return true;
for(int i = 1; i <= 4; i++)
{
if(r[pr[k]] & (1 << i)) continue;
if(c[pc[k]] & (1 << i)) continue;
if(block[f(pr[k], pc[k])] & (1 << i)) continue;
mat[pr[k]][pc[k]] = '0' + i;
r[pr[k]] |= (1 << i);
c[pc[k]] |= (1 << i);
block[f(pr[k], pc[k])] |= (1 << i);
if(dfs(k + 1)) return true;
r[pr[k]] ^= (1 << i);
c[pc[k]] ^= (1 << i);
block[f(pr[k], pc[k])] ^= (1 << i);
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ca++)
{
for(int i = 1; i <= 4; i++)
scanf("%s", mat[i] + 1);
num = 0;
memset(r, 0, sizeof(r));
memset(c, 0, sizeof(c));
memset(block, 0, sizeof(block));
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= 4; j++)
if(mat[i][j] == '*') pr[num] = i, pc[num++] = j;
else r[i] |= (1 << (mat[i][j] - '0'));
for(int j = 1; j <= 4; j++)
for(int i = 1; i <= 4; i++)
if(mat[i][j] != '*') c[j] |= (1 << (mat[i][j] - '0'));
for(int k = 0; k < 4; k++)
for(int i = mr[k]; i <= mr[k] + 1; i++)
for(int j = mc[k]; j <= mc[k] + 1; j++)
if(mat[i][j] != '*') block[k] |= (1 << (mat[i][j] - '0'));
dfs(0);
printf("Case #%d:\n", ca);
for(int i = 1; i <= 4; i++)
printf("%s\n", mat[i] + 1);
}
return 0;
}