【发布时间】:2017-12-30 21:27:45
【问题描述】:
我有一个矩形巧克力棒,由黑色、白色或混合的正方形组成。条不大于 50x50 方格。我应该在两个人之间划分栏(一个得到所有白色方块,一个得到黑色方块,混合的无关紧要),通过水平或垂直破解它。我应该找到这种裂缝最少的方法。
我收到了这个输入:
M N(行数,列数) 然后 M 行是 N 个数字长(0 表示白色,1 表示黑色,2 混合) 因此,例如 bar 描述如下:
4 4
0 1 1 1
1 0 1 0
1 0 1 0
2 0 0 0
总共可以破解七次来分割。
而这个至少需要24个裂缝:
5 8
0 1 0 1 0 1 0 2
1 0 2 0 2 0 1 0
0 2 0 2 0 1 0 2
1 0 2 0 2 0 1 0
0 1 0 1 0 1 0 2
我正在考虑将巧克力棒分成两块这样的事情,以便将两个新制作的巧克力棒块分开所需的未来裂缝总和是所有可能裂缝中最小的可能(即高度 -1 + 宽度当前条块的-1被破解)
也感谢 zenwraight,我设法编写了解决此问题的代码,但我遇到了另一个问题,它确实效率低下,如果起始巧克力棒变得大于 30x30,它实际上将无法使用。 无论如何源代码(用C编写):
#include <stdio.h>
#include <stdlib.h>
const int M, N;
int ****pieces;
int r = 0;
int ri = 0;
int inf;
void printmatrix(int **mat, int starti, int startj, int maxi, int maxj) {
for (int i = starti; i < maxi; i++) {
for (int j = startj; j < maxj; j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
int minbreaks(int **mat, int starti, int startj, int maxi, int maxj, int depth) {
if (pieces[starti][startj][maxi][maxj] != 0) {
r++;
return pieces[starti][startj][maxi][maxj];
} else {
ri++;
int vbreaks[maxj - 1];
int hbreaks[maxi - 1];
for (int i = 0; i < maxj; i++) {
vbreaks[i] = inf;
}
for (int i = 0; i < maxi; i++) {
hbreaks[i] = inf;
}
int currentmin = inf;
for (int i = starti; i < maxi; i++) {
for (int j = startj; j < maxj - 1; j++) {//traverse trough whole matrix
if (mat[i][j] != 2) {
for (int k = startj + 1; k < maxj; k++) {//traverse all columns
if (vbreaks[k - 1] == inf) {//traverse whole column
for (int z = starti; z < maxi; z++) {
if (mat[z][k] != 2 && mat[i][j] != mat[z][k]) {
/* printmatrix(mat, starti, startj, maxi, maxj);
printf("brokenv in depth:%d->\n", depth);
printmatrix(mat, starti, startj, maxi, k);
printf("and\n");
printmatrix(mat, starti, k, maxi, maxj);
printf("****\n");*/
vbreaks[k - 1] = minbreaks(mat, starti, startj, maxi, k, depth + 1) + minbreaks(mat, starti, k, maxi, maxj, depth + 1);
if (vbreaks[k - 1] < currentmin) {
currentmin = vbreaks[k - 1];
}
break;
}
}
}
}
}
}
}
for (int i = starti; i < maxi - 1; i++) {
for (int j = startj; j < maxj; j++) {
if (mat[i][j] != 2) {
for (int k = starti + 1; k < maxi; k++) {
if (hbreaks[k - 1] == inf) {
for (int z = startj; z < maxj; z++) {
if (mat[k][z] != 2 && mat[i][j] != mat[k][z]) {
/* printmatrix(mat, starti, startj, maxi, maxj);
printf("brokenh in depth:%d->\n", depth);
printmatrix(mat, starti, startj, k, maxj);
printf("and\n");
printmatrix(mat, k, startj, maxi, maxj);
printf("****\n");*/
hbreaks[k - 1] = minbreaks(mat, starti, startj, k, maxj, depth + 1) + minbreaks(mat, k, startj, maxi, maxj, depth + 1);
if (hbreaks[k - 1] < currentmin) {
currentmin = hbreaks[k - 1];
}
break;
}
}
}
}
}
}
}
if (currentmin == inf) {
currentmin = 1;
}
pieces[starti][startj][maxi][maxj] = currentmin;
return currentmin;
}
}
void alloc(int i, int j) {
pieces[i][j] = malloc(sizeof (int*)*(M + 1));
for (int y = i; y < M + 1; y++) {
pieces[i][j][y] = malloc(sizeof (int)*(N + 1));
for (int x = j; x < N + 1; x++) {
pieces[i][j][y][x] = 0;
}
}
}
int main(void) {
FILE *file = fopen("pub08.in", "r");
//FILE *file = stdin;
fscanf(file, "%d %d", &M, &N);
int **mat = malloc(sizeof (int*)*M);
pieces = malloc(sizeof (int***)*M);
for (int i = 0; i < M; i++) {
mat[i] = malloc(sizeof (int)*N);
pieces[i] = malloc(sizeof (int**)*N);
for (int j = 0; j < N; j++) {
int x;
fscanf(file, "%d", &x);
mat[i][j] = x;
alloc(i, j);
}
}
inf = M * (M + 1) * N * (N + 1) / 4 + 1;
int result = minbreaks(mat, 0, 0, M, N, 0);
printf("%d\n", result);
printf("ri:%d,r:%d\n", ri, r);
return (EXIT_SUCCESS);
}
我的目标是解决这个输入:
40 40
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 0 2 1 2 1 2 0 0 1 2 2 0 0 0 0 0 0 0 0 1 1 2 1 2 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 2 0 1 1 1 1 1 0 0 1 2 2 0 0 0 0 0 1 0 0 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 2 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1 1 2 2 0 0 0 1 2 2 1 2 1 0 0 0 0 0 1 2 1 2 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 2 2 1 2 0 0 0 0 0 2 1 2 2 0 0 0 0 0 2 1 2 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 2 2 2 1 1 0 0 0 0 0 2 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 0 0
0 2 1 2 1 0 2 2 2 2 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 0 2 2 1 0 0 0 0 0 0
0 2 2 1 2 0 1 2 2 1 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 1 0 0 0 0 0 0
0 2 2 1 2 0 0 0 0 2 1 2 1 2 1 1 2 0 2 0 0 0 0 0 0 0 1 2 2 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 2 2 2 2 1 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 2 1 1 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 0 0 0 0
0 0 0 0 0 0 0 2 1 2 0 0 2 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 1 2 2 1 0 0 0 0 2 0 1 1 1 2 1 2 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 2 1 2 2 2 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 1 2 1 1 2 2 0 0 0 0 0
0 0 0 0 0 0 1 2 1 2 2 1 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 0 2 1 2 0 0 0 0 0
0 0 0 0 0 0 1 2 2 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0
0 0 0 0 0 0 1 1 1 1 1 2 2 0 0 0 0 0 0 0 0 1 1 1 2 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 1 2 2 2 1 1 1 0 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 0 0 2 2 2 1 0
0 0 0 0 0 0 0 0 0 1 2 1 2 0 0 0 0 0 0 0 0 1 1 1 2 2 0 0 0 0 0 0 0 0 0 1 2 1 1 0
0 0 0 2 1 1 2 2 0 1 2 1 1 0 0 0 0 0 2 2 1 2 2 1 2 2 0 0 0 0 0 0 0 0 0 1 2 2 2 0
0 0 0 2 2 2 1 1 0 0 1 2 2 2 0 0 0 0 2 2 2 1 1 2 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 1 2 2 1 1 0 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 2 2 2 2 1 0 1 1 1 1 1 1 2 1 1 2 2 1 0 1 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 0 0 2 1 1 1 2 1 2 0 0 1 2 1 2 1 2 2 0 0 0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 2 2 1 1 2 2 1 1 1 1 1 1 1 2 1 0 0 0 0 0 0 0 2 2 2 0 0 0
0 0 0 0 0 0 0 1 1 1 2 0 0 1 1 1 2 2 1 2 2 2 1 0 0 0 1 1 1 0 0 0 0 0 1 2 1 0 0 0
0 0 0 0 0 0 0 2 1 1 2 0 0 0 0 0 0 2 2 2 1 1 1 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 2 1 1 1 2 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 0 0 0 0 0 1 1 2 0 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 2 1 0 0
0 0 0 0 0 0 0 0 0 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
不到 2 秒,这比我当前的程序要快得多。这个裂缝的最小数量是 126。
【问题讨论】:
-
很抱歉,但我不确定我做错了什么?为什么我得到这么多反对票?我觉得这个问题够清楚了吧?
-
在发布下一个问题之前,您应该先通过the tour,然后再转到Help Section 阅读What types of questions should I avoid asking?。然后,如果您确定您的问题符合规则,请阅读 How to Ask a question on StackOverflow 以便能够提出一个有用、格式正确且主题相关的问题。
-
嗯,其实我花了很多时间思考解决方案,但我没有想出任何合理的方案,所以我才在这里问。顺便说一句,我并不是要一个完整的工作程序,只是提示如何解决这个问题
-
4x4 矩阵可以在 6 个裂缝中完成: 1.:第一行。 2.:第一行的第一件。 3.:从休息块 3x4 第一列。 4.:第二列,5.:最后一列。 6.:从第 3 列开始,破解最后一行(=piece)。 6 个步骤。
标签: algorithm recursion dynamic-programming rectangles