| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1741 人关注过本帖, 1 人收藏
标题:神奇的古尺
只看楼主 加入收藏
梁2
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2012-12-5
收藏
得分:0 
回复 3楼 heroinearth
有道理。。。
2013-10-17 17:26
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
尝试非暴力求解,但不太满意,先抛砖引玉吧。(用的是C++语言)
程序代码:
#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 编辑 ]
2013-10-18 09:50
快速回复:神奇的古尺
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.090664 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved