Algorithm 从二进制矩阵中划掉坏行
我们得到了n边的平方二元矩阵。Algorithm 从二进制矩阵中划掉坏行,algorithm,matrix,Algorithm,Matrix,我们得到了n边的平方二元矩阵。 我们将考虑包含至少一个0作为“坏”的任何行或列。 任务是清空所有错误的行和列。 任务需要使用0(1)个额外内存 1 1 0 0 0 0 1 1 1 => 1 0 0 1 0 1 0 0 0 困难的是,当我们在遍历过程中发现坏线时,我们不能将它们置零(否则,我们将始终以零矩阵结束)。所以我在寻找这样一种数据结构或数据表示方式,这样它可以在算法在矩阵中迭代时存储关于坏行和坏列的所有信息。实际上,我们只需要2n位就可以得到答案:我们需要知道每一
我们将考虑包含至少一个0作为“坏”的任何行或列。 任务是清空所有错误的行和列。
任务需要使用0(1)个额外内存
1 1 0 0 0 0
1 1 1 => 1 0 0
1 0 1 0 0 0
困难的是,当我们在遍历过程中发现坏线时,我们不能将它们置零(否则,我们将始终以零矩阵结束)。所以我在寻找这样一种数据结构或数据表示方式,这样它可以在算法在矩阵中迭代时存储关于坏行和坏列的所有信息。实际上,我们只需要2n位就可以得到答案:我们需要知道每一行和列是好(1)还是坏(0)。每个单元格中的答案将是行和列答案的乘积 让我们将大部分信息存储在矩阵本身中: 我们可以使用第一行为所有列保留记录(0或1),但第一行除外, 第一列保留除第一行以外的所有行的记录,我们还需要两个位来保留第一行和第一列的记录 首先,我们得到这两个额外的位(检查第一行和第一列) 然后查找并存储其他行和列的记录 然后计算除第一行和第列之外的所有矩阵中的结果位
最后:如果第一行不好,则应将其置为空,否则应保持原样,第一列也应如此。作为第一步,在网格中查找0。如果我们找不到,我们就完了 如果我们找到一个,我们就知道应该使0的行和列中的所有1都为空 因此,由于我们知道所有这些单元格的最终值,我们可以使用该行和该列作为临时布尔标志,来确定同一行或同一列是否包含任何0 确切的过程是:
- 通过矩阵查找0
- 跟踪找到的0的坐标
- 在每行和每列上循环,检查该行或列是否包含0,并适当设置标志
- 然后再次在矩阵上循环,对于不在标志行或列中的每个1,检查是否设置了行或列标志,如果设置了,则将该1设置为0
- 然后将行和列中用作标志的所有单元格设置为0
1 1 0 1 0
1 1 1 0 1
1 0 1 1 1
1 1 1 1 1
1 1 1 1 1
然后我们寻找一个零,假设我们找到了顶部中间的一个
然后,我们使用顶行和中间列作为标记,以确定同一行/列是否包含0:
0 1 0 1 1
1
1
0
0
然后,如果设置了标志行/列,我们循环其他单元格,将1设置为0:
0 0 0 0
0 0 0 0
1 0 0 0
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
1 0 0 0 0
1 0 0 0 0
<>这显然是在原地进行的,我只是为了直观地把它分开, < p>我写了C++实现,Natalya Ginzburg有帮助的答案。 把它留在这里,以防对别人有用。
#包括
#包括
#包括
#包括
#包括
#包括
类矩阵{
公众:
矩阵(int n):
侧(n),
步幅(圆形(n/8+1)),
是否很好(正确),
is0ColGood(正确){
printf(“%d%d\n”,侧面,跨步);
数据=新字符[跨步*边];
memset(数据,0,步幅*侧面*大小(字符));
如果(!数据){
printf(“alloc问题”);
出口(1);
}
填充();
打印();
}
~Matrix(){
如果(数据)
删除数据;
}
无效过程(){
对于(int j=0;j#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
class Matrix {
public:
Matrix(int n):
side(n),
stride( round(n/8+1) ),
is0RowGood(true),
is0ColGood(true) {
printf("%d %d\n", side, stride);
data = new char[stride*side];
memset(data, 0, stride*side*sizeof(char) );
if( !data ) {
printf("alloc problem\n");
exit(1);
}
fill();
print();
}
~Matrix() {
if(data)
delete data;
}
void process() {
for( int j = 0; j < side; ++j ) {
if(getEl(0, j) == false) {
is0RowGood = false;
break;
}
}
for( int i = 0; i < side; ++i ) {
if(getEl(i, 0) == false) {
is0ColGood = false;
break;
}
}
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if(!getEl(i,j)) {
setEl(i,0, false);
break;
}
}
}
for( int j = 1; j < side; ++j ) {
for( int i = 1; i < side; ++i ) {
if(!getEl(j,i)) {
setEl(0, i, false);
break;
}
}
}
// nullify now
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if( !getEl(0,j) || !getEl(i,0) )
{
crossRow(i);
crossCol(j);
}
}
}
if(!is0RowGood)
crossRow(0);
if(!is0ColGood)
crossCol(0);
printf("--\n");
print();
}
private:
void crossRow(int x) {
for(int i = 0; i < side; ++i ) {
setEl(x, i, false);
}
}
void crossCol(int x) {
for(int i = 0; i < side; ++i ) {
setEl(i, x, false);
}
}
void print() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
printf(" %d ", getEl(i,j));
}
printf("\n");
}
}
void fill() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
usleep(15);
setEl(i, j, (rand() % 30 == 0) ? 0 : 1);
}
}
}
bool getEl(int i, int j) {
int offset = trunc(i/8) + j*stride;
char byte = data[offset];
return byte & static_cast<char>(pow(2, i%8));
}
bool setEl(int i, int j, bool val) {
int offset = trunc(i/8) + j*stride;
if(val)
data[offset] |= static_cast<char>(pow(2, i%8));
else
data[offset] &= static_cast<char>(255-pow(2, i%8));
}
bool is0RowGood;
bool is0ColGood;
char* data;
int side;
int stride;
};
int
main( int argc,
const char** argv ) {
if(argc < 2) {
printf("give n as arg\n");
exit(1);
}
time_t t;
if(argc == 3)
t = atoi(argv[2]);
else {
t = time(NULL);
printf("t=%d",t);
}
srand (t);
int n = atoi( argv[1] );
printf("n=%d\n",n);
Matrix m(n);
m.process();
}