| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 867 人关注过本帖
标题:一个题目以及自己写的程序,求指导一下。
只看楼主 加入收藏
真想学C
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2014-4-25
结帖率:40%
收藏
已结贴  问题点数:10 回复次数:14 
一个题目以及自己写的程序,求指导一下。
描述
有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式。如:
n=5,5个数分别为1,2,3,4,5,t=5;
那么可能的组合有5=1+4和5=2+3和5=5三种组合方式。
输入
输入的第一行是两个正整数n和t,用空格隔开,其中1<=n<=20,表示正整数的个数,t为要求的和(1<=t<=1000)
接下来的一行是n个正整数,用空格隔开。
输出
和为t的不同的组合方式的数目。

#include<stdio.h>
#include <math.h>
int main()
{
    int n,i,j,s,t;
    s=0;
    printf("请输入数字个数以及所需要的和\n");
    scanf("%d,%d",&n,&t);
    int a[n];
    for(i=0;i<n;i++)
    {
    scanf("%d",&a[i]);
    }
    for(i=0;i<n;i++)
    {
        if (t==a[i])
            s=s++;
    }
    for(i=0;i<n;i++)
    {
        j=i+1,
        for(;j<n;j++)
        {
            if(a[i]+a[j]==t)
                s=s++;
        }
    }
    printf("%d",s);
    return 0;
}



编译错误,不知道怎么修改。

[ 本帖最后由 真想学C 于 2014-4-25 21:21 编辑 ]
搜索更多相关主题的帖子: 正整数 include 
2014-04-25 21:20
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:2 
编译错误?  什么错误?

大家使用的编译器不见得和你使用的就是相同的,所出现的错误信息也不见得相同.  既然自己编译了,出现了错误了,就应该根据编译器的提示来进行修改.

代码测试环境:  WinXP+C-Free5.0.
2014-04-25 21:50
我是书生
Rank: 1
等 级:新手上路
帖 子:1
专家分:2
注 册:2014-4-25
收藏
得分:2 
你这个应该是用变量n定义了数组。。这是不行的。。。你可以用以常变量定义比如用  #define N  1000;
然后只用这个数组a【N】的前n个。。。
2014-04-25 22:42
神机军师
Rank: 7Rank: 7Rank: 7
来 自:游鱼潜水
等 级:黑侠
威 望:2
帖 子:202
专家分:542
注 册:2013-12-21
收藏
得分:2 
这个 应该是先把数字全部提取出来吧,然后排一下序 呃后面的算法 没想到简洁的 坐等楼下

未知令人期待!
2014-04-25 22:47
新手中路
Rank: 2
等 级:论坛游民
帖 子:7
专家分:18
注 册:2014-4-23
收藏
得分:2 
a[n]不能这样定义,,,定义数组里面的要是常量
2014-04-25 23:06
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
简单的写了下. 仅供参考. 不要拿这去交作业.  
虽然能实现你的要求,但里面的有个小地方我也不知道该怎么改好一些,反正这样写有点别扭.
你的代码中使用了可变长的数组. C89标准不支持这个, C99才支持. 目前大部分的编译器对C99支持不够友好,还是按C89来吧.
程序代码:
#include "stdio.h"
int main()
{
    int inputnum,sumnum,d,g=1,i,j;
    int addition[20];
    printf("请输入需要输入的数字个数:\n");
    printf("请注意,该数字只能介于0-20之间.\n"); 
    scanf("%d",&inputnum);
    if(inputnum<=0||inputnum>20)
    {   
         printf("你的输入有误,请重新输入.\n");
         fflush(stdin);
         scanf("%d",&inputnum);
    }
    printf("请输入和数:\n");
    printf("请注意,该数字只能介于1-1001之间.\n") 
    scanf("%d",&sumnum);
    if(sumnum<1||sumnum>1000)
    {   printf("你的输入有误,请重新输入.\n"); 
        fflush(stdin);
        scanf("%d",&sumnum);
    }
    printf("请输入 %d 个整数.\n",inputnum);
    for(i=0;i<inputnum;i++)
    {
        scanf("%d",&addition[i]);
    }
    printf("\n\n麻利麻利哄\n\n\n");
    
    for(i=0;i<inputnum;i++)
    {
        if(sumnum==addition[i])
        {   printf("%d,%d=%d.\n",g,sumnum,addition[i]);
            g++;
        }
        
        for(j=i+1;j<inputnum;j++)
        {
            d=addition[i]+addition[j];
            if(sumnum==d)
            {printf("%d,%d=%d+%d\n",g,sumnum,addition[i],addition[j]);
                 g++;
            }
        }
    }
        printf("和为%d的组合共有%d种.\n",sumnum,g-1);
    
    return 0;
}

代码测试环境:  WinXP+C-Free5.0.
2014-04-25 23:13
kwxx
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:309
专家分:913
注 册:2009-5-11
收藏
得分:2 
我记得见过这个题目,但是好像有很简练的方法。坐等学习。
2014-04-25 23:18
kwxx
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:309
专家分:913
注 册:2009-5-11
收藏
得分:0 
题目要求可以是任意个数之和吧?你们只考虑了不多于两个数的和。
2014-04-25 23:32
神机军师
Rank: 7Rank: 7Rank: 7
来 自:游鱼潜水
等 级:黑侠
威 望:2
帖 子:202
专家分:542
注 册:2013-12-21
收藏
得分:0 
想了一个算法,不能验证正确与否,不过思路都写上了,希望有些用
程序代码:
/*描述
有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式。如:
n=5,5个数分别为1,2,3,4,5,t=5;
那么可能的组合有5=1+4和5=2+3和5=5三种组合方式。
输入
输入的第一行是两个正整数n和t,用空格隔开,其中1<=n<=20,表示正整数的个数,t为要求的和(1<=t<=1000)
接下来的一行是n个正整数,用空格隔开。
输出
和为t的不同的组合方式的数目。
*/

// 想来想去就想到了个递归。。。注释解释了一下算法,从main函数看是依次看
#include <stdio.h>

int sum = 0; // 这是结果,全局变量,初始化一定为0,开始计数后在别的地方不要改变其值

void Count(int *array, int n, int t,int s, int elmNum)
{ // 这是个递归函数,也是这个算法的核心部分,利用int指针array(你也可以
  // 理解成数组名,但是这的的确确是指针,它们还是有一定区别的),剩余数组个数
  // n,调用函数前已经有的和s以及所需要的组合元素个数剩余个数elmNum的传递来实现
  // 递归。
  // 在执行这个函数前,在Process函数里面找到了maxNum的值,所以就是当elmNum为1至
  // maxNum时,每次都调用Count函数,即调用:
  // Count(a, n, t, 0, 1);
  // Count(a, n, t, 0, 2);
  // ...
  // Count(a, n, t, 0, maxNum);
  // 在这个时,a还是main函数里面数组名,也就是数组第一个元素的地址(在调用Process
  // 函数时,已经把指针值--数组地址 传递给了a,就是上面的啊);上面的n是main函数
  // 输入的n的个数;此时刚刚调用Count函数,还没有开始计算,所以已有的和s还是0。
  // 当最后那个参数,也就是elmNum是1时,说明再加上一个元素的值就能满足想要组合元素
  // 的个数了,此时进行t与(s+某元素的值)的值比较,如果相等,就说明有一种情况符合,
  // 进行sum++的操作。
  // 
  // 下面重点来了:
  // 如果,所需的elmNum大于1,那么在这一次的函数执行是不好把剩下的全部组合情况(是排列
  // 组合的组合 意思自己理解就是 C A 那个)一一清查的,因为不确定elmNum的值,有可能
  // 是3,4甚至更多。所以,想到利用递归,通过每调用一次Count函数减少elmNum的1的值,
  // 直到elmNum为1,就用上面的思路求出来。
  // 那么怎么排查,怎么依次把所有的情况都列出来呢?
  // 说一下思路,当elmNum是一个确定值的时候,例如3,那么就是说t是由三个元素组合的(他
  // 们都不重复,就先假设全部的数组假设就是1,2,3...10,t是10)。那么你可以想象,如果每
  // 个组合都从小到大排列了一下(例如1,2,7;1,3,6;2,3,5等等)一定是从最小的1开始,
  // 把有1的组合情况取出来,剩下组合情况再把有2取出来(这里面就没有1了,剩下的还没有
  // 取出来的也没有2了),依次取到数组的最后一个元素。
  // 这时候,取出来1就代表这个1已经是组合里面的一员了,组合的和s就是1,这时候1这个
  // 元素就不参与剩下的组合情况的调配,这时候,剩下的elmNum就是2,剩下的数组就从2开
  // 始,数组的地址也就把1这第一个元素的地址去掉然后从a+1(为什么不是a+sizeof(int)?
  // 因为a是int类型指针,加1以后的访问是说加了一个int型数据长度以后的访问)开始,这
  // 时候数组元素个数就是n-1。然后调用Count(a+1, n-1, t, 1, 2)开始递归。
  // 而如果取出来的是2,那么就是说组合里面没有1,因为已经排查了,那么这时候:剩下
  // 的elmNum就是2,剩下的数组就从3开始,数组的地址也就把1,2这两个元素的地址去掉然
  // 后从a+2开始,剩余数组元素个数是n-1。然后调用Count(a+2, n-1, t, 2, 2)开始递归。
  // 同上类情况,组合里面最小的数当依次是i=1,2,3...时候就能用个循环结构调用
  // Count(a+1+i, n-1, t, s, 2);
  // 注意,数组里面的1元素的下标是0所以传递指针是a+1+i,而和s要用s+a[i]表示加上了这个
  // 数组元素,让下面的递归能够知道,好去判定最后与t的比较。
  //
  // 下面继续:
  // 当1被取出来后,调用了Count(a+1, n-1, t, 1, 2)也就是调用了Count(a+1, 9, t, 1, 2)
  // 就是说剩下两个元素要在main函数里面的后九个元素里面寻找,思路也是和上面3个找第
  // 一个时一样(这也是为什么能用递归了,而且这里应该也能发现排序的好处,不排序算法不容
  // 易实施)。然后找到了组合的第二个元素(这里的举例,组合需要三个),再通过循环找
  // 第三个,这时候elmNum是1,就开始进行与t的比较了。
  //
  // 说一下碰到的特殊情况:
  // if (n < elmNum)
  // 这个是说剩余数组元素已经少于需要的元素个数,因为前面是循环进行递归的会把所有情况
  // 都列出来,那么在这个例子里面有可能会调用Count(某地址, 0, t, 1, 2),就没有剩下可选
  // 的元素了,所以也不可能有符合条件的情况了,直接返回上一级循环,节约点时间,少出错。
  // if (s + array[i] <= t)
  // {
  //     Count(array + i + 1, n - i - 1, t, s + array[i], elmNum - 1);
  // }
  // 这里是要选择array[i]作为所需要的组合元素之一,不管剩下几个还没有找的元素,假如
  // 此时s + array[i] > t 那么就可以不用执行下去了,已经大于t了不管怎么加都会一直大
  // 于t(都是正整数,题目已经说明了)所以只有当s + array[i] <= t时候才继续下一个环
  // 节的递归调用。

    int i; // 循环计数变量
    fprintf(stdout, "\n\n\n此时最大组合元素剩余%d个,数组元素剩余%d个,和是%d。\n",
        elmNum, n, s);
    if (n < elmNum)
    { // 一种特殊情况
        fprintf(stdout, "此时剩余数组元素已经少于需要的元素个数,不成立。\n");
        return;
    }
    if (1 == elmNum)
    { // elmNum为1时,进行判定
        for (i = 0; i < n; i++)
        {
            if (s + array[i] == t)
            {
                sum++;
                fprintf(stdout, "这是第%d种情况,和是%d,最后数组元素是%d。\n",
                    sum, s, array[i]);
            }
        }        
    }
    else
    { // elmNum不是1时候递归调用
        for (i = 0; i < n; i++)
        { 
            if (s + array[i] <= t)
            { // else情况是另一种特殊情况,上面有说明
                Count(array + i + 1, n - i - 1, t, s + array[i], elmNum - 1);
            }
        }
    }
    return;
}

void Process(int a[], int n, int t)
{ // 这是初步处理函数,为了求一下组合的最大个数,例如例子里面有
  // 5  1,4  2,3 其实最大的组合个数是2。至于怎么求,就用到了刚才
  // 排序的数组,你从最小的开始加,依次加下去如果加到的一个数,
  // 加之前小于t,加之后大于t,那么这个maxNum就是这个数的数组下标
  // 了。maxNum就是maxElementNumber,还是那个1,2,3,4,5的例子,1+2是3
  //  小于t,1+2+3是6大于t,那么组成t最多也就是2个,正好是3的元素
  // 下标(1的下标是0,往后依次是1,2...)。而且这已经是最小的组合了
  // 相同数目的元素任意其他情况都比这种情况的和要大,所以这就是极限
  // 情况了,然后就利用某些算法(我这里想到的是递归)依次求出来当组
  // 合数是1个,2个...maxNum个的情况(sum是全局变量,一定初始化为0)。

    int maxNum = 0;   // 最大的个数组合可能的个数
    int s      = 0;   // 求数组元素依次相加的和,别忘了初始化0
    int i;            // 循环计数变量

    for (i = 0; i < n; i++)
    {
        s += a[i];
        if (s > t)
        {
            maxNum = i;
            break; // 找到满足条件值以后可以直接跳出循环体了
        }
    }
    if ((n == i) && (sum < t))
    { // 一种特殊情况,如果输入数字是1,2,3 而所求和是10,就没有符合题意的组合了
        fprintf(stdout, "\n所有值的和都小于要求t\n");
        return;
    }
    if (0 == maxNum)
    { // 另一种特殊情况,如果maxNum是0,说明要么循环完没找到符合要求的下标,就是
      // 上面那种情况,已经return了,另一种就是数组最小值比t大,那么也不可能有符
      // 合题意的组合。
        fprintf(stdout, "\n数组最小值都大于要求t\n");
        return;
    }

    fprintf(stdout, "\nmaxNum是%d个。\n", maxNum);
    for (i = 1; i <= maxNum; i++)
    { // 从1到maxNum开始调用这个Count函数
        Count(a, n, t, 0, i);
    }
    return;
}

void main()
{
    int n;         // 数组个数
    int t;         // 所求组合的和
    int i, j;      // 循环计数变量
    int temp;      // 排序时候的中间变量
    int array[20]; // 记录数组 因为说明不多于20个所以就定一个20个长度的

    fprintf(stdout, "请输入数字个数与求和的值:");
    fscanf(stdin, "%d%d", &n, &t);
    for (i = 0; i < n; i++)
    { // 把数字录入数组里面,这个录入方式不严谨,如果是oj的话,可能这里会出问题
        fprintf(stdout, "请输入第%d个数值:", i+1);
        fscanf(stdin, "%d", &array[i]);
        fprintf(stdout, "你输入的数值是:%d\n", array[i]); 
         // 上面一句其实就是怕输入流哪里出问题,容易验证
    }

    fprintf(stdout, "\n排序前的数组是:\n");
    for (i = 0; i < n; i++)
    { // 排序前输出数组
        fprintf(stdout,"%-4d", array[i]);
    }
    for (i = 0; i < (n - 1); i++)
    { // 排序,按顺序排序有利于算法实现。。
        for (j = i + 1; j < n; j++)
        {
            if (array[i] > array[j])
            {
                temp     = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
    fprintf(stdout, "\n排序后的数组是:\n");
    for (i = 0; i < n; i++)
    { // 排序后输出数组,正好可以比较,顺便简单检查一下正误
        fprintf(stdout,"%-4d", array[i]);
    }

    Process(array, n, t); // 调用处理函数,把n,t还有数组的首地址传过去
    fprintf(stdout, "\n一共有%d种情况。\n", sum); // 输出结果,sum是开头定义的全局变量
}

未知令人期待!
2014-04-26 01:27
真想学C
Rank: 1
等 级:新手上路
帖 子:31
专家分:0
注 册:2014-4-25
收藏
得分:0 
回复 8 楼 kwxx
是一个数或者两个数的和等于t。不是任意几个数的和
2014-04-26 11:23
快速回复:一个题目以及自己写的程序,求指导一下。
数据加载中...
 
   



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

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