回复 3楼 heroinearth
有道理。。。
程序代码:#include <stdio.h>
struct foo
{
bool scale[37]; // 从0到36,是否有刻度
foo()
{
// 一开始时第0和第36是等效于有刻度的
scale[0] = 1;
for(size_t i=1; i<36; ++i) scale[i]=0;
scale[36] = 1;
}
size_t get_last_cannot() const // 返回最大的那个不能被度量的长度
{
bool flags[37] = { 0 };
for( size_t i=0; i<37; ++i )
{
if( scale[i] == 0 )
continue;
for( size_t j=i+1; j<37; ++j )
{
if( scale[j] == 0 )
continue;
flags[j-i] = true;
}
}
size_t ret;
for( ret=36; flags[ret]; --ret );
return ret;
}
};
void bar( struct foo f, size_t time )
{
size_t len = f.get_last_cannot();
if( len == 0 ) // 全部完成
{
for( size_t i=1; i<36; ++i )
{
if( f.scale[i] )
printf( "%d ", (int)i );
}
printf( "\n" );
return;
}
if( time == 0 ) // 8个刻度用完,失败
return;
for( size_t i=0; i<37; ++i )
{
if( !f.scale[i] )
continue;
if( i+len <= 36 ) // 可以在第i个刻度右侧距离len处增加一个新刻度
{
f.scale[ i+len ] = true;
bar( f, time-1 );
f.scale[ i+len ] = false;
}
if( i >= len ) // 可以在第i个刻度左侧距离len处增加一个新刻度
{
f.scale[ i-len ] = true;
bar( f, time-1 );
f.scale[ i-len ] = false;
}
}
}
int main()
{
bar( foo(), 8 );
//1 5 9 16 23 30 33 35 (35 1 33 5 30 9 23 16 )
//1 3 6 13 20 27 31 35 (35 1 3 31 6 27 13 20 )
//1 5 9 16 23 30 33 35 (1 35 33 5 30 9 23 16 )
//1 3 6 13 20 27 31 35 (1 35 3 31 6 27 13 20 )
return 0;
}输出有重复,因为一开始可以 先定1再定35,也可以先定35再定1,……
---------------------------------------------------------------
将代码优化一下(算法没变)
程序代码:#include <stdio.h>
#include <math.h>
struct foo
{
unsigned char scales[10];
size_t scales_length;
unsigned long long lens;
foo()
{
scales[0] = 0;
scales[1] = 36;
scales_length = 2;
lens = 1ull<<36;
}
foo AppendScale( signed char scale ) const
{
foo r = *this;
r.scales[r.scales_length] = scale;
for( size_t i=0; i<r.scales_length; ++i )
r.lens |= 1ull<<abs(r.scales[i]-scale);
++r.scales_length;
return r;
}
size_t get_last_cannot_length() const
{
size_t len;
for( len=35; lens&(1ull<<len); --len );
return len;
}
};
void bar( struct foo f )
{
size_t len = f.get_last_cannot_length();
if( len == 0 )
{
for( size_t i=2; i<10; ++i )
printf( "%d ", (int)f.scales[i] );
printf( "\n" );
return;
}
if( f.scales_length == 10 )
return;
for( size_t i=0; i<f.scales_length; ++i )
{
if( f.scales[i]+len <= 36 ) // 可以在第i个刻度右侧距离len处增加一个新刻度
bar( f.AppendScale(f.scales[i]+len) );
if( f.scales[i] >= len ) // 可以在第i个刻度左侧距离len处增加一个新刻度
bar( f.AppendScale(f.scales[i]-len) );
}
}
int main()
{
bar( foo() );
//1 5 9 16 23 30 33 35 (35 1 33 5 30 9 23 16 )
//1 3 6 13 20 27 31 35 (35 1 3 31 6 27 13 20 )
//1 5 9 16 23 30 33 35 (1 35 33 5 30 9 23 16 )
//1 3 6 13 20 27 31 35 (1 35 3 31 6 27 13 20 )
return 0;
}[ 本帖最后由 rjsp 于 2013-10-18 15:08 编辑 ]







