题目链接如下:
一开始的代码如下,题目说|n| < 64, 感觉有点问题,一开始我设的是mat[6][maxx][maxx], 也就是假设n最大是32,代码在测试集上都没问题,但提交oj就一直WA,折磨了我很久;改成7就AC了....
这个解法的基本思想是,每一个小格子扫描过去的时候,直接把它对应的2*2, 4*4, 8*8,...等等大格子也计算了,即,里面都是黑色则标记为1,都是白色则标记为0,杂色则标记为2. 这样,每次把格子由大到小划分,只要大格子已经标记为1或者0,就不用再往下划分了,只有标记为2的格子需要进一步划分。
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
const int maxx = 64;
// #define debug
int n, t, kase = 0;
char ss[65];
int mat[7][maxx][maxx];
char matrix[maxx][maxx];
std::vector<int> ans;
int du[] = {0, 0, 0, 1, 1};
int dv[] = {0, 0, 1, 0, 1};
void div(int k, int startR, int startC, int order, int path){
int rank = (int)(log2(k) + 0.01);
int temp = mat[rank][startR / k][startC / k];
int tempPath = path + order * pow(5, (int)(log2(n) + 0.01 - 1 - rank));
if (temp == 1){
ans.push_back(tempPath);
} else if (temp == 2){
div(k / 2, startR, startC, 1, tempPath);
div(k / 2, startR, startC + k / 2, 2, tempPath);
div(k / 2, startR + k / 2, startC, 3, tempPath);
div(k / 2, startR + k / 2, startC + k / 2, 4, tempPath);
}
}
void matToPath(){
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
for (int k = 1; k < 7; ++k){
mat[k][i][j] = -1;
}
}
}
for (int i = 0; i < n; ++i){
scanf("%s", ss);
for (int j = 0; j < n; ++j){
mat[0][i][j] = ss[j] == '1' ? 1 : 0;
for (int k = 1; k <= (int)(log2(n) + 0.01); ++k){
int rank = 1 << k;
int a = i / rank;
int b = j / rank;
if (mat[k][a][b] == -1){
mat[k][a][b] = mat[0][i][j];
} else if ((mat[k][a][b] == 0 || mat[k][a][b] == 1) && mat[k][a][b] != mat[0][i][j]){
mat[k][a][b] = 2;
}
}
}
}
div(n, 0, 0, 0, 0);
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); ++i){
printf("%d%s", ans[i], i % 12 == 11 || i == ans.size() - 1 ? "\n" : " ");
}
printf("Total number of black nodes = %d\n", ans.size());
}
void fillBlack(int k, int startR, int startC, int t){
if (!t){
for (int i = startR; i < startR + k; ++i){
for (int j = startC; j < startC + k; ++j){
matrix[i][j] = '*';
}
}
} else {
int temp = t % 5;
fillBlack(k / 2, startR + du[temp] * k / 2, startC + dv[temp] * k / 2, t / 5);
}
}
void pathToMat(){
n = -n;
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
matrix[i][j] = '.';
}
}
while (scanf("%d", &t) == 1 && t != -1){
fillBlack(n, 0, 0, t);
}
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
printf("%c", matrix[i][j]);
}
printf("\n");
}
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("1.txt", "w", stdout);
#endif
while (scanf("%d\n", &n) == 1 && n){
if (kase){
printf("\n");
}
printf("Image %d\n", ++kase);
ans.clear();
if (n > 0){
matToPath();
} else {
pathToMat();
}
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
上面这个代码开始一直因为mat分层太少WA,所以不得已,看了一下别人的思路,然后用递归写了另一个解法,代码如下:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
const int maxx = 64;
// #define debug
int n, t, kase = 0;
char ss[65];
int mat[maxx][maxx];
char matrix[maxx][maxx];
std::vector<int> ans;
int du[] = {0, 0, 0, 1, 1};
int dv[] = {0, 0, 1, 0, 1};
int judge(int k, int startR, int startC, int order, int depth, int path){
int currPath = path + order * pow(5, depth);
if (k == 1){
if (mat[startR][startC] == 1){
return 1;
}
return 0;
}
int a[5];
for (int i = 1; i <= 4; ++i){
a[i] = judge(k / 2, startR + du[i] * k / 2, startC + dv[i] * k / 2, i, depth + 1, currPath);
}
if (a[1] == 1 && a[2] == 1 && a[3] == 1 && a[4] == 1){
return 1;
}
if (!a[1] && !a[2] && !a[3] && !a[4]){
return 0;
}
for (int i = 1; i <= 4; ++i){
if (a[i] == 1){
ans.push_back(currPath + i * pow(5, depth + 1));
}
}
return 2;
}
void matToPath(){
ans.clear();
for (int i = 0; i < n; ++i){
scanf("%s", ss);
for (int j = 0; j < n; ++j){
mat[i][j] = ss[j] == '1' ? 1 : 0;
}
}
if (judge(n, 0, 0, 0, -1, 0) == 1){
ans.push_back(0);
}
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); ++i){
printf("%d%s", ans[i], i % 12 == 11 || i == ans.size() - 1 ? "\n" : " ");
}
printf("Total number of black nodes = %d\n", ans.size());
}
void fillBlack(int k, int startR, int startC, int t){
if (!t){
for (int i = startR; i < startR + k; ++i){
for (int j = startC; j < startC + k; ++j){
matrix[i][j] = '*';
}
}
} else {
int temp = t % 5;
fillBlack(k / 2, startR + du[temp] * k / 2, startC + dv[temp] * k / 2, t / 5);
}
}
void pathToMat(){
n = -n;
std::fill(matrix[0], matrix[0] + maxx * maxx, '.');
while (scanf("%d", &t) == 1 && t != -1){
fillBlack(n, 0, 0, t);
}
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
printf("%c", matrix[i][j]);
}
printf("\n");
}
}
int main(){
#ifdef debug
freopen("0.txt", "r", stdin);
freopen("1.txt", "w", stdout);
#endif
while (scanf("%d\n", &n) == 1 && n){
printf("%s", kase ? "\n" : "");
printf("Image %d\n", ++kase);
if (n > 0){
matToPath();
} else {
pathToMat();
}
}
#ifdef debug
fclose(stdin);
fclose(stdout);
#endif
return 0;
}