| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 792 人关注过本帖
标题:向beyondyf大哥请教,并和大家一起研究。
取消只看楼主 加入收藏
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
结帖率:99.34%
收藏
已结贴  问题点数:20 回复次数:4 
向beyondyf大哥请教,并和大家一起研究。
下面是我给出的一道题:
大家一起来做题:二维数组取数求和。给力--->给分!
输入一个n行m列(2 <= n <= 16 , 2 <= m <= 24)二维数组,每行的元素值都是0 1 2 3 …… m -1;要求从每一行取一个元素,使取得的n个元素的和等于m-1.问有多少种取法,并打印出每种取法对应的n个元素。

比如 3 * 4 的二维数组a   0 1 2 3
                         0 1 2 3
                         0 1 2 3
取数使a[0][?] + a[1][?] + a[2][?] = 3 有多少种取法,及其对应的3个数。取法数太大的可以不用打印对应元素。
连接是:https://bbs.bccn.net/thread-359913-1-1.html

杨大哥给了代码我贴上来,并请教几个问题(为了测试数据,我改了下范围和循环,核心没动)。
程序代码:
#include 
#include 
#define N_MAX        100
#define M_MAX        100

__int64 a[N_MAX + 1][M_MAX];

void init()
{
        int i, j;
        for(i = 1; i <= N_MAX; i++)
        for(j = 1; j < M_MAX; j++)
                a[i][j] = a[i][j - 1] + a[i - 1][j] + 1;
        for(i = N_MAX; i; i--)
        for(j = M_MAX - 1; j; j--)
                a[i][j] -= a[i][j - 1];
}

__int64 cal(int n, int m)
{
        if(n <= 0 || m <= 0) return 0;
        if(n == 1) return m;
        if(m == 1) return n;
        return cal(n, m - 1) + cal(n - 1, m) + 1;
}

__int64 c(int n, int m)
{
        __int64 r;
        int i;
        for(r = i = 1; i < n; i++)
        {
                r *= m - 1 + i;
                r /= i;
        }
        return r;
}

void print(int n, int m, int index)
{
        int i;
        static int list[N_MAX];
        if(n <= 1)
        {
                for(i = 0; i < index; printf("%d ", list[i++]));
                printf("%d\n", m);
                return;
        }
        for(list[index] = i = 0; i <= m; list[index] = ++i)
                print(n - 1, m - i, index + 1);
}

int main()
{
        int n, m;
        int start, end;

        while(1)
        {
          init();
          printf("Please input n & m:");
          scanf("%d %d", &n, &m);         
          if(a[n][m - 1] <= 10000) print(n, m - 1, 0); else printf("it's too large.\n");
          printf("The methods count is %I64d\n", a[n][m - 1]);
          printf("The mothods count is %I64d\n", c(n, m));
          if (n <= 16 && m <= 21)
          {
            start = clock();
            printf("The methods count is %I64d\n", cal(n, m - 1) - cal(n, m - 2));
            end = clock();
            printf("time is :%-3dsecond!\n",(end - start)/CLK_TCK);
          }
        }
    return 0;
}
上面题供了3种放法.一时难以领会,特别是打印函数,print(n, m - 1, 0); 为什么index传入的是0,而在整个
print函数中index自身貌似没发生变化,那么for(i = 0; i < index; printf("%d ", list[i++]));这个句能循环起来吗?
下面是我的测试数据:
图片附件: 游客没有浏览图片的权限,请 登录注册
图片附件: 游客没有浏览图片的权限,请 登录注册

为什么输入1 1时3个函数中有个不一样,输入到 32 32时数学方法应该是正确的吧,变成负数说明数太大装不下了,而第一种方法还能显出一个整数?
搜索更多相关主题的帖子: 大哥 元素 
2012-02-03 13:21
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
搞清楚点眉目了。
 if(n == 1)
        {
                for(i = 0; i < index; printf("%d ", list[i++]));
                printf("%d\n", m);
                return;
        }
当n==1时index应该是n-1,那么for(i = 0; i < index; printf("%d ", list[i++]));输出的是前面N-1个元素,    也就是输出到LIST[N-2].
printf("%d\n", m);再补上最后一个此时的函数传来的M值,一起就是N个元素,因为一组输出必须是N个元素。

 for(list[index] = i = 0; i <= m; list[index] = ++i)
                print(n - 1, m - i, index + 1);
从0到m(主函数开始传入的是m-1符合题意)每一类都递归调用print,而每一类index的初始值都是0,即LIST[0].他是在递归调用中随着n递减而递增的,当n减到1,index就增加到n-1,此时m通过n-1次(m-i)的变化传入
print(1, m, n-1);中,由printf("%d\n",m);追加打印出来,补齐n个元素。

杨大哥不知道我上面的理解对不对。
发现这个print()函数太神奇了。

图片附件: 游客没有浏览图片的权限,请 登录注册





[ 本帖最后由 有容就大 于 2012-2-4 10:34 编辑 ]

梅尚程荀
马谭杨奚







                                                       
2012-02-04 10:26
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
回复 4楼 beyondyf
杨大哥再请教个问题,即把m个相同的球放到n个不同的盒子中,有多少种放法的问题:
我这么考虑的,第一个位置放盒子,有n种选择,后面的看成n-1个位置和m个不同球的排列。
--> S1 = n * P(n+m-1,n+m-1),但是球的相同的要除以m个球的全排列
--> S2 = S1 / P(m, m),又只考虑后面n-1个盒子的位置排列即可,球放入盒子间隙(包括两头)的
                      排列是重复的,要除以n个间隙的全排列
--> S3 = S2 / P(n, n).
--> S3 = n * (n+m-1)!/ (n!*m!)
       = (n+m-1)!/((n-1)!*m!)
       = C(n+m-1, n-1)
       = C(n+m-1, m)
不知道对不对,还有没有更好的理解方式?

梅尚程荀
马谭杨奚







                                                       
2012-02-04 11:30
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
回复 7楼 beyondyf
55555看了你的解释我觉得自己悲催了啊

梅尚程荀
马谭杨奚







                                                       
2012-02-04 12:10
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
收藏
得分:0 
谢谢杨大哥鼓励。Z版……汇+编

梅尚程荀
马谭杨奚







                                                       
2012-02-04 16:01
快速回复:向beyondyf大哥请教,并和大家一起研究。
数据加载中...
 
   



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

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