『每日一题 2012-04-17』巧排数字

问题描述:

将1,2,3,……,20这20个连续的自然数排成一圈,使任意两个相邻的自然数之和均为素数

强人的思路:

1 找出所有和为素数的数对

2 找Hamilton环

找所有和为素数的数对的方法:

1,2,3,……,20任意两数之和的最大值为39,可取40。故首先,我们找出1到40之间的所有素数,实现函数如下:

int create_prime(int *a, int max)  // 找到  1 到 max 间的所有素数 

{   

    int *x;

    int i,j; 

    x = (int *)alloca(sizeof(int)*(max+1));

    for(i=1;i<=max;i++)  // initialize x[]

        x[i] = 0;

    x[2] = 1;  // 2 是素数

    for(i=3;i<=max;i+=2)

        x[i] = 1;

    

    for(i=3;i<max/3;i+=2)

        for(j=i*3;j<=max;j+=2*i)

            x[j] = 0;

    

    j = 0;

    for(i=0;i<=max;i++)

        if(x[i] == 1)

            a[j++] = i;

    return j; 

}

 

其中,数组a保存找到的1到40之间所有的素数,结果按下标顺序从小到大保存。函数最后返回找到的素数的个数。

然后构建一个map(二维数组)来保存所有和为素数的数对,实现函数如下:

void create_map(void)

{

    int a[20]; // 保存 1 ——40 之间的素数 

    int len;   // 1 -- 40之间素数的个数 

    int i,j,k;

    len = create_prime(a,40);

    for(i=1;i<=20;i++) {

        degree[i] = 0;

        for(j=0;j<len;j++) {

            k = a[j] - i;

            if(k <=0)

                continue;

            if(k <= 20)

                map[i][degree[i]++] = k;

            else

                break;

        }

    }

}

找Hamilton环的实现,就是回溯搜索(类似于堆栈)的方法,来找出所有符合条件的结果。

这里要注意考虑清楚 前进 和回退 条件。实现为:

int main()

{

    int i,j;

    create_map();

    for(i=1;i<=20;i++)

    {

        printf("%d:\t",i);

        for(j=0;j<degree[i];j++)

        {

            printf("%d\t",map[i][j]);

        }

        printf("\n");

    }

    

    ham[0] = 1; // 第一个节点选择的数字 为 1

    ham_len = 1;

    

    for(i=0;i<=20;i++) 

    {

        cur_use[i] = 0;

        cur_pos[i] = 0;

    }

    cur_use[1] = 1;

        

    j = 1; //下个需要处理的数字

    

    cur_pos[1] = 0;

    while(1)

    {

        while(cur_pos[j]<degree[j])

        {

            if(cur_use[map[j][cur_pos[j]]] == 0) //找到了可用数字 

            {

                cur_use[map[j][cur_pos[j]]] = 1;

                ham[ham_len++] = map[j][cur_pos[j]];

                break;

            }

            cur_pos[j]++;

        }

        

        if(cur_pos[j] < degree[j]) 

        {           

            if(ham_len==20 && map[ham[19]][0]==1)

            {

                for(i=0;i<20;i++)

                    printf("%d->",ham[i]);

                printf("\n");

                system("pause");

            }

            else

            {

                j = ham[ham_len-1];

                cur_pos[j] = 0;

                

                continue;

            }            

        }

        

        if(--ham_len <= 0)

            break;

        cur_use[ham[ham_len]] = 0;

        j = ham[ham_len-1];

        cur_pos[j]++;  

    } 

    system("pause");

    return 0;

}

时间: 2024-10-31 05:40:21

『每日一题 2012-04-17』巧排数字的相关文章

『每日一题 2012-04-18』将真分数分解为埃及分数

问题描述: 分子为1的分数称为埃及分数,现输入一个真分数,请将该分数分解为埃及分数. 如:8/11=1/2+1/5+1/55+1/110. *问题分析与算法设计 若真分数的分子a能整除分母b,则真分数经过化简就可以得到埃及分数,若真分数的分子不能整除分母,则可以从原来的分数中分解出一个分母为b/a+1的埃及分数.用这种方法将剩余部分反复分解,最后可得到结果. #include<stdio.h> int main(void) { long int a,b,c; printf("Plea

『每日一题 2012-03-25』巧填数字

问题描述: *问题分析与算法设计 问题本身并不复杂,可以对乘式中的每一位使用穷举法,最终可以得到结果.本题的关键在于怎样有效的判断每个部分积的每一位是否满足题意,这一问题处理不好,编写的程序会很长.程序实现中采用了一个判断函数,通过传入函数的标志字符串对所有的数进行统一的判断处理. #include<stdio.h> void print(long a,long b,long s1,long s2,long s3); int jud(long q,char *pflag); int main(

“济南车管”中新辟“每日一题”栏目

本报7月8日讯(记者王若松)"学习时间又到了,亲们答对了么?"近日,济南市车管所在其http://www.aliyun.com/zixun/aggregation/1144.html">腾讯微博"济南车管"中新辟"每日一题"栏目,通过微博的形式帮助广大车主及驾考人员随时随地加强道路交通理论学习,强化安全出行意识. 记者了解到,"每日一题"中的所有题目均出自最新的驾考理论考试题库,供博友们学习参考.

借题“2012搞笑诺贝尔奖” 解读网站优化中的几点疑惑

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 2012搞笑诺贝尔奖颁发了很多有意思的奖项,这些奖项看似无聊无趣甚至无厘头,但是它的一些观点却起我的思考,这些思考和奖项本身无关,只是给了我一些启迪,通过这些思绪,让我感觉到,作为一名草根站长,要想成功就要解放思想.遇到不解的问题,不要急着否定,说不定那是个提升自己能力的机会!下面的分析和奖项内容无关,意在引题. 换个角度思考,或许就能找到突

近期ubuntu 14.04 cpu占用高排障

    近期linux使用总是cpu达到满值, 双核cpu其中一个核总是100%,另一个核正常.top之发现输入法框架fcitx满载,直接kill之,发现搜狗输入法不能用了,随即输入如下命令: fcitx fcitx-qimpanel 输入法恢复鸟,cpu也变为0鸟,鸥鸟!

OJ题:输入一个多位的数字,求各数位相加。

题目内容: 输入一个多位的数字,1求各数位相加. 例如输入12345,则计算1+2+3+4+5=15 输入格式: 一个整数 输出格式: 一个整数 输入样例: 1234567890 输出样例: 45 时间限制:500ms内存限制:32000kb 实现程序: #include <stdio.h> #include <stdlib.h> #include <string.h> int cnt_count(int value) { int count = 0 , cnt = 0

2012蓝桥杯【初赛试题】 巧排扑克牌

题目描述:    小明刚上小学,学会了第一个扑克牌"魔术",到处给人表演.魔术的内容是这样的:     他手里握着一叠扑克牌:A,2,....J,Q,K 一共13张.他先自己精心设计它们的顺序,然后正面朝下拿着,开始表演.     只见他先从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是A:然后再从最下面拿一张放到最上面,再从最下面拿一张翻开放桌子上,是2:......如此循环直到手中只有一张牌,翻开放桌子上,刚好是K.     这时,桌上牌的顺序是:A,2,3,4,5,6,

使用WPF动画编程的几点注意事项[转]

1.       在FrameworkElement.Triggers中启动动画的几点备注: ·         此Triggers集合中只支持EventTrigger,使用其他类型的Trigger将会加载失败. ·         EventTrigger.SourceName指定的元素必须在当前的EventTrigger所应用的元素的逻辑子树内.如果EventTrigger应用于自身元素,则不需要制定SourceName属性. ·         当对一个依赖属性应用了动画后,再对该属性赋值

WEB架构师成长之路

牛人就是是牛人,看了他写的,再回过头来想想,我为什么写不出来呢~ 来源地址:http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html 赵学智@行胜于言 本人致力于学习面向对象.设计模式.重构.极限编程.大型网站架构设计.管理等知识,希望有不正确之处多多指出,共同学习提高,为了方便查阅,特做出索引一页. 序言 WEB架构师成长之路之一-走正确的路 WEB架构师成长之路之二-大牛的法宝 WEB架构师成长之路之三-架构师都要懂哪些