华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1948|回复: 9
打印 上一主题 下一主题

经典的M选N程序及其变形

[复制链接]

61

主题

147

帖子

563

积分

超级版主

Rank: 8Rank: 8

积分
563
跳转到指定楼层
楼主
发表于 2014-10-18 18:29:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先,我们用递归做一个标准的m选n程序:
#include <iostream>
using namespace std;
const int m=5,n=3;  //假设5选3
int a[n];  //每个位置上面存放的数字
bool b[m]; //B数组表示某个数字是否被用过
void mysearch(int i)
{
    int j,k;
    if (i==n)
    {
        for (j=0; j<=n-1; j++) cout<<a[j];
        cout<<endl;
    }
    else for (k=0; k<=m-1; k++)
            if (b[k])
            {
                a[i]=k;
                b[k]=false;
                mysearch(i+1);
                b[k]=true;
            }
}
int main()
{
    for (int i=0; i<=m-1; i++) b[i]=true;
    mysearch(0);
    return 0;
}
回复

使用道具 举报

61

主题

147

帖子

563

积分

超级版主

Rank: 8Rank: 8

积分
563
推荐
 楼主| 发表于 2014-10-18 18:42:54 | 只看该作者
今年初中组初赛有个题目是问8个球装在5个袋子里有多少种装法,其中袋子可以为空。可以用这种方法来做,尽管笨了一点,但是很好理解。
#include <iostream>
using namespace std;
const int m=8,n=5;
int a[n];
void mysearch(int i)
{
    int j,k,s=0;
    if (i==n)
    {
        for (j=0; j<=n-1; j++) s+=a[j];
        if (s==10) {for (j=0; j<=n-1; j++) cout<<a[j];cout<<endl;}
    }
    else for (k=(i==0?0:a[i-1]); k<=m-1; k++)
        {
            a[i]=k;
            mysearch(i+1);
        }
}
int main()
{
    mysearch(0);
    return 0;
}
回复 支持 2 反对 0

使用道具 举报

4

主题

68

帖子

1592

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1592
推荐
发表于 2014-10-18 18:34:45 | 只看该作者

沙发

本帖最后由 hr567 于 2014-10-18 18:43 编辑

顶!!!!抢沙发了……
  1. char *s = "Good!";
  2. std::cout <<  s << endl;
  3. return 0;
复制代码

这个人很懒,不想写签名。
回复 支持 1 反对 0

使用道具 举报

61

主题

147

帖子

563

积分

超级版主

Rank: 8Rank: 8

积分
563
推荐
 楼主| 发表于 2014-10-18 18:32:23 | 只看该作者
本帖最后由 diggersun 于 2014-10-18 18:39 编辑

现在我们将它改成5个数字(0,1,2,3,4)中选3个的组合,所谓组合,就是没有顺序,我们也可以认为,是后面一个数字大于前面一个数字的排列。
  1. #include <iostream>
  2. using namespace std;
  3. const int m=5,n=3;
  4. int a[n];
  5. void mysearch(int i)
  6. {
  7.     int j,k;
  8.     if (i==n)
  9.     {
  10.         for (j=0; j<=i-1; j++) cout<<a[j];
  11.         cout<<endl;
  12.     }
  13.     else for (k=(i==0?0:a[i-1]+1); k<=m-1; k++)  
  14.               {
  15.                 a[i]=k;
  16.                 mysearch(i+1);
  17.                }
  18. }
  19. int main()
  20. {
  21.     mysearch(0);
  22.     return 0;
  23. }
复制代码
因为后面一个数字比前面一个大,所以绝对不会有重复,可以省略B数组,程序13行是控制循环变量K的值,做法比较特殊,当i==0的时候说明是第一个位置上的数字,从0起步,否则,从上一个数字+1 起步,这个小技巧请大家学会。
回复 支持 1 反对 0

使用道具 举报

4

主题

68

帖子

1592

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1592
5#
发表于 2014-10-18 18:41:03 | 只看该作者
顶!!!!抢沙发
  1. char *s = "Good!";
  2. std::cout <<  s << endl;
  3. return 0;
复制代码
这个人很懒,不想写签名。
回复 支持 反对

使用道具 举报

0

主题

7

帖子

148

积分

注册会员

Rank: 2

积分
148
6#
发表于 2014-10-18 18:48:10 | 只看该作者
  1. printf("\110\105\99\101\33");
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 16:41 , Processed in 0.102499 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表