searchosearchd Now m1t Lights L1 Now sesearchr Lightsoffnow ht
search Lights isearchhsearchso Off fsearcho Off h1 Now a Lightsoffnow e Now r Lights hsearch
i Now hsearchs search searchosearch searchseasearchch Lights se Off r1h
s Lights a Lights c Off N N1w Off w
e Tag rch Lights
o1 Now searchi Lights hsearchssearchr Lights
igh Off s Now f Off n Lights w Lights 1 searchff Lights _ Tag L
g Now t Off Lights searchi Now h Lightsoffnow s Lightsoffnow t Off Lsearchg Off tsearch search searchi Lights h Off s Now M
Of Now search Tag osearch 1 Lightsoffnow osearch Off 1,searchisearcht Lightsoffnow n Tag {search
void matrix_init_const(MATRIX m, char c, int n1, int n2){}
void matrix_init_E(MATRIX e, int n){}
void matrix_init_H(MATRIX h, int n){}
}
void matrix_copy(MATRIX m, CONST_MATRIX k, int n){}
void matrix_copy2(MATRIX m, CONST_MATRIX k, int n1, int n2){}
void vector_copy(VECTOR v, CONST_VECTOR w, int n){}
void matrix_output2(CONST_MATRIX m, int n1, int n2){}
printf("n");
}
}
void matrix_output(CONST_MATRIX m, int n){}
printf("n");
}
}
void vector_output(VECTOR v, int n){}
void Usage(const char *program_name){}
MATRIX P0,P1,H;
VECTOR ME;
MATRIX init;
//First we need to solve equation P*X(n) = ME;
//There could be multiple solutions
//For each solution X(n), try
//X(n-1) = INIT+ H*X(n);
//X(K) = INIT + H*X(k+1)+X(k+2);//for k<n-1
void Solve(MATRIX P, VECTOR ME, int n, int m)
{}else{}
temp = ME[t];
ME[t] = ME[j];
ME[j] = temp;
}
for(j=0;j<m;j++){}
ME[j]^=ME[t];
}
}
t++;
}
}
for(;t<m;t++){}
}
fprintf(stderr,"Freedom factor = %d/n", freedom_count);
if(failed){}
if(freedom_count>0){}else if(delta>0){}
}
}
//Now ME hold's one solution for X[n],
//And random reset index inside freedom_index of ME to 0, 1
// will result in another solution for X[n];
//Output one solution
#ifdef _DEBUG
printf("ME:");vector_output(ME, m);printf("n");
printf("H:/n");matrix_output(H,m);
printf("init:/n");
matrix_output(init,m);
#endif
if(freedom_count>=20)freedom_count=20;//do not search too much
int u;
int best_one_count=n*m+1;
MATRIX bm=matrix_alloc2(n,m);
for(u=0;u<1<<freedom_count;u++)
{}
}
}else{}
}
matrix_mul_vector(x[n-2],H,x[n-1],m);
vector_sum(x[n-2],init[n-1],m);
for(k=n-3;k>=0;k--){}
int lc=maxtrix_count_one(x,n,m);
if(lc<best_one_count){}
matrix_free(x);
}
matrix_output2(bm,n,m);
matrix_free(bm);
free(freedom_index);
}
void parse(int argc, char **argv, int *pn,int *pm){}else if(n<=1){}else{}
}else if(argc==3){}else if(n<=1||m<=1){}else{}
}else{}
for(j=0;j<m;j++){}
init[i][j]=s[j]-'0';
}
}
*pm=m;*pn=n;
return;
}
}
int main(int argc, char **argv){}
parse(argc,argv,&n,&m);
#ifdef _DEBUG
printf("Input:/n");
matrix_output2(init,n,m);
#endif
ME = vector_alloc(m);
temp_vector = vector_alloc(m);
P0 = matrix_alloc(m);
P1 = matrix_alloc(m);
H = matrix_alloc(m);
temp_matrix = matrix_alloc(m);
matrix_init_H(H,m);
matrix_init_E(P0,m);
matrix_init_H(P1,m);
#ifdef _DEBUG
printf("P(0):/n");matrix_output(P0,m);
printf("P(1):/n");matrix_output(P1,m);
#endif
matrix_mul_vector(ME, P0, init[0], m);
matrix_mul_vector(temp_vector, P1, init[1], m);
#ifdef _DEBUG
printf("M(0):");vector_output(ME,m);printf("n");
printf("M(1):");vector_output(temp_vector,m);printf("n");
#endif
vector_sum(ME,temp_vector,m);
#ifdef _DEBUG
printf("S(1):");vector_output(ME,m);printf("n");
#endif
for(i=2;i<=n;i++){}
}
Solve(P1, ME, n,m);
matrix_free(init);
vector_free(ME);
vector_free(temp_vector);
matrix_free(P0);
matrix_free(P1);
matrix_free(H);
matrix_free(temp_matrix);
return 0;
}
在网络上,我还找到一个俄国人的一个证明:如果开始所有的灯都是开的,那么必然存在一种方案将所有的灯关闭.这个证明用到代数知识,只是所用定理应该是应用在实数域上的,运用在有限域上不知道是否正确:
Puzzle 2: for this problem, we are giving up the detailed information about how the lights are connected. We are left knowing only that the connections are reflexive and symmetric, and that our task is to go from all lights ON to all lights OFF. Lossers gives a short explanation of how to see that this is so. First, we define the obvious matrix A with 1's indicating which switches control which lights. The matrix is symmetric and has 1's on its diagonal.
Now it's equivalent to show that there is some strategy x of button pushing that can go from all lights OFF to all lights ON. But that's just asking if there is a vector x such that
A * x = d,
where d is the vector of all 1's. That is equivalent to asking if d is in the column space of A. And that is equivalent to asking if the "perpendicular space" of A' is contained in the "perpendicular space" of d. In other words, it is enough to show that A'*x=0 implies d'*x=0.
So let x be any vector in the perpendicular space of A'. Then
Sum (1 <= i <= N) xi * Ai,j = 0
for all j. This implies
Sum ( 1 <= j <= N ) Sum (1 <= i <= N) xi * Ai,j * xj = 0,
Now we know that A is symmetric (assumption 2). Therefore, in the preceding sum, let us consider, for distinct i and j every pair of terms
xi * Ai,j * xj + xj * Aj,i * xi =
( Ai,j + Aj,i ) * xi * xj =
2 * Ai,j * xi * xj = 0
because we are working in arithmetic module 2! Therefore, all the offdiagonal terms pair up and drop out.
Our sum now only involves the diagonal terms:
Sum (1 <= i <= N) xi2 * Ai,i = 0
Now Ai,i = 1, because the light-switch relationship is reflexive (assumption 1), and di = 1 too, so in the sum, we can replace Ai,i by di. Moreover, we know that xi2=xi, because xi is either 0 or 1. Therefore, we now have
Sum (1 <= i <= N) xi * di = 0
Hence x is in the perpendicular space of d. This means d is in the column space of A, so a button strategy exists that turns a set of "off" lights all "on", and the same strategy will turn a set of "on" lights all "off".
关于这个问题,很早以前还有一种算法,将整个矩阵看成一个向量,那么M=N*N的灯就要解一个M*M解线性方程组,算法复杂度要大很多:
#include <stdio.h>
#define MAXN 100
#define MAXTRIX_SIZE (MAXN*MAXN)
char **m;
char *b;
char *r;
int *index;
int main(int argc,char *argv[]){}else{}
if(n>MAXN||n<=0){}
last=n*n;
m=(char **)malloc(sizeof(char*)*last+sizeof(char)*last*last);
b=(char *)malloc(sizeof(char)*last);
r=(char *)malloc(sizeof(char)*last);
index=(int *)malloc(sizeof(int)*last);
if(m==NULL||b==NULL||r==NULL||index==NULL){}
m[0]=(char *)(m+last);
for(i=1;i<last;++i)m[i]=m[i-1]+last;
memset(m[0],0,sizeof(char)*last*last);
for(i=0;i<last;++i)index[i]=i;
//initialize data
for(i=0;i<n*n;++i){}
for(i=0;i<last;++i){}
if(j==n*n){}
}else{}
swap=b[i];
b[i]=b[j];
b[j]=swap;
for(j=i+1;j<n*n;++j){}
}
}
}
if(last<n*n){}
}
}
for(i=last-1;i>=0;--i){}
}
}
}
if(last==n*n){}
printf("n");
}
}
else{}
printf("Free parameter count=%d/n",n*n-last);
for(k=0;k<(1<<(n*n-last));++k){}
for(i=0;i<last;++i){}
if(r[i])iswap++;
}
printf("A good result k=%d,operation count=%d/n",k,iswap);
for(i=0,j=0;j<n;++j){}
printf("n");
}
if(iswap<small){}
}
{}
for(i=0;i<last;++i){}
if(r[i])iswap++;
}
for(i=0,j=0;j<n;++j){}
printf("n");
}
}
iswap=small;
}
printf("Total %d operation/n",iswap);
return 0;
}
2楼 intfree () 回复于 2002-02-25 17:53:05 得分 1
无论n是多少,这个程序输出的Free parameter,都恰恰是我程序所输出的一半。这个程序没有产生所有解,不知你是否为了忽略旋转翻转等本质相同的解,而作了特殊处理。n=9时好像有问题,我的解需要25步:
100001001
001100000
001100110
100000110
000010000
011000001
011001100
000001100
100100001
Top
3楼 mathe () 回复于 2002-02-25 19:54:59 得分 0
You're right. It's my bug.
I should modify
if(j==n*n){}
To
if(j==n*n){}
Then it seems impossible to search for n=47 in such a way.
Because we need to search for 1G possible solutions for n=47.
It seems further effort needed for large free parameter.
#include <stdio.h>
#define LIMIT 10000
void output_polynomial(char p[LIMIT], int n)
{}
printf("n");
}
int main()
{}
P[0]=P0[i];
printf("P[%d]=",n);output_polynomial(P,n);
S[n]=P[n];
for(i=n-1;i>=0;i--)S[i]^=P[i];
printf("S[%d]=",n);output_polynomial(S,n);
for(i=n;i>=0;i--){}
}
return 0;
}