| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3610 人关注过本帖
标题:求高手编写一个将十个数分成五组的程序!
只看楼主 加入收藏
广陵绝唱
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:29
帖 子:3607
专家分:1709
注 册:2008-2-15
收藏
得分:0 
to:风居住的街道
void select(int k)
{
    int i;
    if (k + 2 == len)
    {
        for (i = 0; i < len; i += 2)
            printf("(%d, %d)", a[i], a[i+1]);
        printf("\n");
        count++;
        return;
    }
    select(k + 2);
/***********************************************************************
    我就是这里弄不明白。函数到这里递归调用了,那么后面的代码在什么时候应用呢?运行到递归语句的时候,应该是立即调用自身,那么后面的这些语句什么时候运行?另外,有些程序在运用递归的时候,函数中写了两条递归语句,那么到底是怎么运行的呢?先运行哪条呢?

    劳烦您分神解答,谢谢~
************************************************************************/
    for (i = k + 2; i < len; i++)
    {
        SWAP(a[k + 1], a[i]);
        select(k + 2);
        SWAP(a[k + 1], a[i]);
    }
}
2008-11-06 23:40
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
收藏
得分:0 
提示:针对上面第二个代码,有几个地方的优化:
1 ans和str没动过(虽然是指针),因此可以提到外面做全局变量,省去了传参的时间。
2 因为str的长度根本就可以确定,所以第二个memmove的操作显得没有意义:可以直接交换当前的值和str的“后面一个”的值,反正知道大小,就可以随时把那个值复制回来
3 从第二点可知,对str,其实我们每次就只用到了“当前位置”一个变量,“最后一个位置的后面一个位置”一个变量(即我们只用了str[i]和str[N]而已),所以str是可以省掉的,单纯用每个循环的两个变量代替就好了
4 很快我们又发现,连两个代替的变量都不需要,因为既然我们可以计算出s的大小,那么我们只要多取一个位置“暂存”当前位置,就可以随时换过来,这样就可以用s本身就可以存储那两个变量了,所以我们一个变量都不需要了。(可能需要一个交换用的临时变量)
5 可以看出,ans除了存答案什么都没做,而答案原来都是在s里面的,s里面有几,ans里面就有几,而且它们之间是可以相互计算位置的,所以可以把那两个我们用到的值存在ans里面,稍微计算一下就可以得到那个值,这样,s本身也就不需要了,值需要在ans里面存下我们需要的所有东西,就可以计算了。
6 再仔细分析一下可以发现,第一次循环,我们的交换是多余的,将调用提出来,然后循环的初始值加一。

经过以上的分析,上面的第二个程序就优化为我的程序了(其实也就是经典的求全排列的程序),现在可以知道我的程序的思路了吧?注意第五步是关键哦~~能看出来,基本上就可以优化了。
2008-11-06 23:43
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
收藏
得分:0 
to:21L

栈知道吧?函数的调用是通过栈进行的,假设不是递归。我们有三个函数f1,f2,f3。假设要互相,调用,f1调用f2,f2调用f3.
如果是人,那么你会怎么做?

“今天天气很好,我们要出去郊游。早晨起床,我刚刚要出门,突然想起来眼镜还没戴,于是匆匆脱下鞋回去找眼镜,找到了,可是眼镜很脏,于是我又带着眼镜跑回了厕所,找到了毛巾擦过眼镜后我回到客厅穿上鞋,就出门了。”

仔细分析上面的过程,可以发现人做事情其实是一个“做最急需要做的事情”的一个过程:找不到眼镜,你不会还傻乎乎地出门,玩到一半再回去找眼镜吧?(可能有人会这么做,我们下面再讨论)。你会做“当前最紧迫的事情”,剩下的事情只好押后。那么这个“做最紧要的事情,当前事情推后”是不是和入栈很像呢?做完了最紧要的事情,我们才会想起去做第二紧要的事情,这个过程是不是又和入栈很像呢?(如果你“忘记”了找眼镜,那么显然某个时候“找眼镜”肯定会成为更紧要的事情,你不得不打断正在做的事情(这件事情入栈),然后去找眼镜,找到后才能继续去做(那件事情出栈),是不是同样也是这个过程呢?)

于是,计算机里面的过程调用就模仿了人类的行为,通过栈,来记录过程调用的情况,对于最开始的f1,f2,f3的例子,也是这样,先调用f1,f1没运行完又要运行f2了,则f1的所有信息入栈,运行f2,f2没运行完又要运行f3,没办法,只好把f2也入栈,最后f3做完了,就让f2出栈,继续f2的过程,最后f2做完了,才会继续做f1。

递归和这个是完全一样的,只是f1,f2,f3是同一个函数,你可以想象它们是茶杯,都是一模一样一家工厂生产出来的茶杯,但是显然你有“一种杯子”和“三个杯子”是不一样的概念,就像你有“一种函数的定义”和拥有“很多函数调用的实例”是不一样的概念一样。别以为一个函数同一时间只能运行一次,你拿了一个杯子了,同样可以拿第二个完全相同,的杯子,尽管和第一个杯子是同种类型,但绝不会是第一个。

现在明白了么?

PS 好像你学C有大半年了吧?怎么会连递归都没有搞懂呢?
再PS 写这么详细了,广陵帮我整理一下,重新发个主题教程吧…………
2008-11-06 23:56
gzbao9999
Rank: 1
等 级:新手上路
威 望:1
帖 子:40
专家分:0
注 册:2008-11-5
收藏
得分:0 
19楼的朋友你讲的不错
我重新整理了一下思路  如下:
共分5组 5组不需要排序

初始化数组 把10个人(10个数放数组中)
在10个人中选第一组 先让数组中第一人过来坐定,那么他可以随意和剩下的9个人进行配对:共有9种可能

把数组剩下的8个重新copy到新数组
在 8个人中选第二组 先让数组中第一人过来坐定,那么他可以随意和剩下的7个人进行配对:共有7种可能

把数组剩下的6个重新copy到新数组
在 6个人中选第三组 先让数组中第一人过来坐定,那么他可以随意和剩下的5个人进行配对:共有5种可能

把数组剩下的4个重新copy到新数组
在 4个人中选第四组 先让数组中第一人过来坐定,那么他可以随意和剩下的3个人进行配对:共有3种可能

把数组剩下的2个重新copy到新数组
在 2个人中选第五组 先让数组中第一人过来坐定,那么他可以随意和剩下的1个人进行配对:共有1中可能

总共可能为9*7*5*3*1=945

下面写程序实现一下
-------------------------------------------
#include<stdio.h>
int cache[10];//存放结果用于打印
int time=0 ;//用于记录所有可能数

//递归
select(int a[],int ceng)
{
    ceng++;
    cache[ceng]=a[0];       //让第一个人先坐定位置
    ceng++;
    int i,j,k ;
    int length=10-ceng+1 ;  //表示当前使用数组a的长度
    int array[length-2];    //用于存放下一层递归所用的数据
   
    for(i=1;i<length;i++)
    {
        cache[ceng]=a[i];   //找到可以配对的人
               
        //如果递归还不够5次(也就是ceng<9时) 为下层的递归拷贝数组,并继续递归
        if(ceng<9)
        {
            k=0 ;
            for(j=1;j<length;j++)
            {
                if(j!=i)
                {
                    array[k]=a[j];
                    k++;
                }
            }
            select(array,ceng);
        }
        
        //如果递归到了第5次(也就是ceng==9的时) 打印结果
        if(ceng==9)print();
    }
}

//用来打印结果
print()
{
    time++;
    int i ;
    for(i=0;i<5;i++)
    printf("%2d,%2d  ",cache[2*i],cache[2*i+1]);
    printf("\n");
}

main()
{
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    int ceng=-1 ;
    select(a,ceng);
    printf("共有%d种可能",time);   
}

[[it] 本帖最后由 gzbao9999 于 2008-11-7 00:43 编辑 [/it]]
2008-11-07 00:23
yuxiang8200
Rank: 1
等 级:新手上路
帖 子:19
专家分:0
注 册:2007-11-25
收藏
得分:0 
#include <stdio.h>
void  group()
{
    int array[] = { 0,1,2,3,4,5,6,7,8,9 };
    int a,b,c,d,e,f,g,h,i,j;
    long sum = 0;
    for(a = 0 ; a < 10 ; a ++ )
    {
        for(b = 0 ; b < 10 ; b++ )
        {
            if(a == b)
                continue;
            for(c = 0 ; c < 10 ; c ++ )
            {
                if(c == a || c == b)
                    continue;
                for(d = 0 ; d < 10 ; d++ )
                {
                    if(d == a || d == b || d == c)
                        continue;
                    for(e = 0 ; e < 10 ; e++ )
                    {
                        if(e == a || e == b || e == c || e == d)
                            continue;
                        for(f = 0 ; f < 10 ; f++ )
                        {
                            if(f == a || f == b || f == c || f == d || f == e)
                                continue;
                            for(g = 0 ; g < 10 ; g++ )
                            {
                                 if(g == a || g == b || g == c || g == d || g == e || g == f)
                                     continue;
                                 for(h = 0 ; h < 10 ; h++ )
                                 {
                                     if(h == a || h == b || h == c || h == d || h == e || h == f || h == g)
                                         continue;
                                     for(i = 0 ; i < 10 ; i++ )
                                     {
                                         if(i == a || i == b || i == c || i == d || i == e || i == f || i == g || i == h)
                                             continue;
                                         for(j = 0 ; j < 10 ; j++ )
                                         {
                                             if(j == a || j == b || j == c || j == d || j == e || j == f || j == g || j == h || j == i)
                                                 continue;
                                             //printf("%d %d %d %d %d %d %d %d %d %d\n",a,b,c,d,e,f,g,h,i,j);
                                             sum++;
                                         }
                                     }
                                 }
                            }
                        }
                    }
                }
            }
        }
    }
    printf("共有%ld种排序方法\n",sum);
}
int main()
{
    group();
    return 0;
}
仅供参考!
2008-11-07 01:30
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
收藏
得分:0 
楼上是人肉深度优先搜索……Orz…………
2008-11-07 08:22
gzbao9999
Rank: 1
等 级:新手上路
威 望:1
帖 子:40
专家分:0
注 册:2008-11-5
收藏
得分:0 
to:风居住的街道

我仔细研究了下你在19L给出的程序
经过我的测试,这种方式确实很快 我目前见到的最快的
也省内存
#define SWAP(a, b) {int t=a; a=b; b=t;} 尤其这种交换方式 很淫荡

在c中int t=a; a=b; b=t;这种交换方式比a=a+b;b=a-b;a=a-b;要快
我在java中测试的结果则相反

顺手用你那种方式写了全排列的算法
唯一的缺憾就是这样算法 输出的数字不能保持增序
我的意思是
比如这种题:用1,2,3,4,5 这5个数字,组成任意5位数,并按从小到大的输出顺序,输出所有可能,就非这种算法所长

用你那种方式写的全排列
------------------------------------------
#include <stdio.h>
#define SWAP(a, b) {int t=a; a=b; b=t;}

int array[10]={0,1,2,3,4,5,6,7,8,9};
int length=10 ;
int time=0;

select(int ceng)
{
    if(ceng+1==length)
    {
        print();
        return ;
    }
    int i ;
    for(i=ceng;i<length;i++)
    {
        if(i!=ceng)
        SWAP(array[ceng],array[i]);
        select(ceng+1);
        if(i!=ceng)
        SWAP(array[ceng],array[i]);
    }
}

print()
{
    time++;
    int i ;
    for(i=0;i<length;i++)
    printf("%d,",array[i]);
    printf("\n");
}
}

main()
{
    select(0);
    printf("time=%d\n",time);
}

[[it] 本帖最后由 gzbao9999 于 2008-11-7 16:23 编辑 [/it]]
2008-11-07 16:20
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
收藏
得分:0 
[bo][un]gzbao9999[/un] 在 2008-11-7 16:20 的发言:[/bo]

顺手用你那种方式写了全排列的算法
唯一的缺憾就是这样算法 输出的数字不能保持增序


我只想说一点,这是全排列,不是组合,如果保持增序了那就根本没排列了……
1,2,3,4全排列有N个,但是如果保持增序,那就只剩下“1,2,3,4”这一种了…………

sigh..........
2008-11-07 19:00
广陵绝唱
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:29
帖 子:3607
专家分:1709
注 册:2008-2-15
收藏
得分:0 
回复 28# 的帖子
---------

    我想,他的意思是这样:如1、2、3这三个数,组合成为123、231,321,312……然后把这几个数排序一下。

    我的理解是这样,如果有错,请勿嘲笑。
2008-11-07 22:13
风居住的街道
Rank: 1
等 级:新手上路
帖 子:374
专家分:0
注 册:2008-10-24
收藏
得分:0 
可是,如果这么说,我的结果的确是排序过的啊……
这是前十个结果:
程序代码:
(1, 2)(3, 4)(5, 6)(7, 8)(9, 10)
(1, 2)(3, 4)(5, 6)(7, 9)(8, 10)
(1, 2)(3, 4)(5, 6)(7, 10)(9, 8)
(1, 2)(3, 4)(5, 7)(6, 8)(9, 10)
(1, 2)(3, 4)(5, 7)(6, 9)(8, 10)
(1, 2)(3, 4)(5, 7)(6, 10)(9, 8)
(1, 2)(3, 4)(5, 8)(7, 6)(9, 10)
(1, 2)(3, 4)(5, 8)(7, 9)(6, 10)
(1, 2)(3, 4)(5, 8)(7, 10)(9, 6)
(1, 2)(3, 4)(5, 9)(7, 8)(6, 10)
(1, 2)(3, 4)(5, 9)(7, 6)(8, 10)
(1, 2)(3, 4)(5, 9)(7, 10)(6, 8)
(1, 2)(3, 4)(5, 10)(7, 8)(9, 6)
(1, 2)(3, 4)(5, 10)(7, 9)(8, 6)
(1, 2)(3, 4)(5, 10)(7, 6)(9, 8)
(1, 2)(3, 5)(4, 6)(7, 8)(9, 10)
(1, 2)(3, 5)(4, 6)(7, 9)(8, 10)
(1, 2)(3, 5)(4, 6)(7, 10)(9, 8)
(1, 2)(3, 5)(4, 7)(6, 8)(9, 10)
(1, 2)(3, 5)(4, 7)(6, 9)(8, 10)
(1, 2)(3, 5)(4, 7)(6, 10)(9, 8)
Hit any key to close this window...

2008-11-07 22:30
快速回复:求高手编写一个将十个数分成五组的程序!
数据加载中...
 
   



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

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