【发布时间】:2017-03-06 20:35:12
【问题描述】:
问题描述: 有一个由 m x n 个正方形组成的巧克力棒。有些方块是黑色的,有些是白色的。有人沿着垂直轴或水平轴打破巧克力棒。然后沿着它的垂直或水平轴再次被打破,它被打破,直到它可以分解成一个单一的正方形,或者它可以分解成只有黑色或只有白色的正方形。使用分而治之的算法,找出可以破坏巧克力棒的方法数。
输入: 第一行告诉你巧克力棒的 m x n 尺寸。在接下来的 m 行中,有 n 个字符告诉您巧克力棒的外观。字母 w 是白色方块,字母 b 是黑色方块。 例如: 3 2 体重秤 wbw
输出: 可破坏巧克力棒的方法数: 对于上面的示例,它是 5(请看附图)。
我尝试使用迭代方法来解决它。不幸的是,我无法完成代码,因为我还不确定如何划分两半(请参阅下面的代码)。有人告诉我递归方法比这容易得多,但我不知道该怎么做。我正在寻找另一种方法来解决这个问题而不是我的方法,或者我正在寻找一些帮助来完成我的代码。
我制作了两个二维数组,第一个用于白色方块,第二个用于黑色方块。我正在用正方形制作一个矩阵,如果有某种颜色的巧克力,那么我在相应的数组中将其标记为 1。 然后,我将上述矩阵的两个累积和组成了两个数组。 然后我创建了一个大小为 [n][m][n][m] 的 4D 数组并进行了四个循环:前两个 (i, j) 增加了矩形数组的大小,即搜索数组的大小(很难解释...),另外两个循环(k,l)正在增加我的起点 x 和 y 在数组中的位置。然后,该算法使用累积和检查从位置 kxl 开始到 k+i x l+j 结束的区域中是否有一个黑色和一个白色方块。如果有,那么我将创建另外两个循环,将区域分成两半。如果在新的两半中仍有黑色和白色方块,那么我将相应的 4D 数组元素增加前半部分的组合数 * 后半部分的组合数。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int counter=0;
int n, m;
ifstream in;
in.open("in.txt");
ofstream out;
out.open("out.txt");
if(!in.good())
{
cout << "No such file";
return 0;
}
in >> n >> m;
int whitesarray[m][n];
int blacksarray[m][n];
int methodsarray[m][n][m][n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
whitesarray[i][j] = 0;
blacksarray[i][j] = 0;
}
}
while(in)
{
string colour;
in >> colour;
for (int i=0; i < colour.length(); i++)
{
if(colour[i] == 'c')
{
blacksarray[counter][i] = 1;
}
if(colour[i] == 'b')
{
whitesarray[counter][i] = 1;
}
}
counter++;
}
int whitessum[m][n];
int blackssum[m][n];
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if(i-1 == -1 && j-1 == -1)
{
whitessum[i][j] = whitesarray[i][j];
blackssum[i][j] = blacksarray[i][j];
}
if(i-1 == -1 && j-1 != -1)
{
whitessum[i][j] = whitessum[i][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i][j-1] + blacksarray[i][j];
}
if(j-1 == -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blacksarray[i][j];
}
if(j-1 != -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitessum[i][j-1] - whitessum[i-1][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blackssum[i][j-1] - blackssum[i-1][j-1] + blacksarray[i][j];
}
}
}
int posx=0;
int posy=0;
int tempwhitessum=0;
int tempblackssum=0;
int k=0, l=0;
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++) // wielkosc wierszy
{
for (posx=0; posx < m - i; posx++)
{
for(posy = 0; posy < n - j; posy++)
{
k = i+posx-1;
l = j+posy-1;
if(k >= m || l >= n)
continue;
if(posx==0 && posy==0)
{
tempwhitessum = whitessum[k][l];
tempblackssum = blackssum[k][l];
}
if(posx==0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[k][posy-1];
tempblackssum = blackssum[k][l] - blackssum[k][posy-1];
}
if(posx!=0 && posy==0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l];
}
if(posx!=0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l] - whitessum[k][posy-1] + whitessum[posx-1][posy-1];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l] - blackssum[k][posy-1] + blackssum[posx-1][posy-1];
}
if(tempwhitessum >0 && tempblackssum > 0)
{
for(int e=0; e<n; e++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
for(int r=0; r<m; r++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
}
}
}
}}
return 0;
}
【问题讨论】:
-
一个澄清:当它可能打破一个正方形(即一个维度是1)时,或者当它是强制(即一个维度是1,另一个是
-
macroland - 这是不同的,因为我的问题是关于黑白巧克力棒。
-
修剪,如果在下一个分割中你会留下一个正方形或者你会留下相同颜色的正方形,你就停止分割。
-
我在澄清英语的歧义——是当我们可以只剩下一个正方形,还是当我们没有其他方法打破标准时?最简单的情况是 4 1 bwbw。我们必须在这里停下来,还是我们必须打破中间的酒吧?
标签: c++ algorithm recursion divide-and-conquer