【编程题目】输入两个整数 n 和 m,从数列 1,2,3.......n 中 随意取几个数, 使其和等于 m ... ★


第 21 题(数组)
2010 年中兴面试题
编程求解:
输入两个整数 n 和 m,从数列 1,2,3.......n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来.

 

我的思路:

从小到大 依次拼凑 后面选的数字 必须比前面大 保证不重复
如: n = 4 m = 8
1 2 3 4 超过8 去掉最后一个数 导数第二个数加一
1 2 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
1 3 4 符合 输出 最后一个数等于 4 去掉最后一个数 导数第二个数加一
1 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
2 3 小于8
2 3 4 超过8 去掉最后一个数 导数第二个数加一
2 4 小于8 最后一个数等于 4 去掉最后一个数 导数第二个数加一
......

 

代码:

/*
第 21 题(数组)
2010 年中兴面试题
编程求解:
输入两个整数  n  和  m,从数列 1,2,3.......n  中  随意取几个数,
使其和等于  m ,要求将其中所有的可能组合列出来.
start time = 15:55
end time = 17:03
*/

#include <iostream>
using namespace std;


int FindCombine(int n, int m)
{
    int method = 0; //一共有多少方法
    if(m <= 0)
    {
        return 0;
    }
    else
    {
        int record[100]; //存储组合当前的取值
        for(int i = 0; i < 100; i++)
        {
            record[i] = i + 1;
        }
        int num = 0; //组合中数字的个数
        int sum = 0; //组合中数字加起来的和

        while(sum < m)
        {
            sum += record[num];
            num++;

            if(sum == m)
            {
                method++;
                printf("组合%d:", method);
                for(int i = 0; i < num; i++)
                {
                    printf("%d ", record[i]);
                }
                printf("\n");

                if(num == 1)
                {
                    return method;
                }
            }
            if((sum >= m) || (sum < m && record[num - 1] == n && num >= 2)) //如果大小超过m 或者 最后一个数字大小等于n 更新record
            {
                num--;
                sum -= record[num];
                num--;
                sum -= record[num];
                if(record[num] <= n)
                {
                    record[num]++;
                    for(int i = 1; i <= n - record[num]; i++)
                    {
                        record[i + num] = record[num] + i;  
                    }
                }
            }
            else if(sum < m && record[num - 1] == n && num == 1)
            {
                return method;
            }
        }
    }
}



int main()
{
    int w = FindCombine(50, 100);
    return 0;
}

 

惯例上网找别人的方法, 一看我就郁闷了, 居然可以用动态规划, 我的算法算是白学了, 到用的时候一点都想不起来。

http://blog.sina.com.cn/s/blog_7571423b01016707.html 里有个详细的分析

http://www.cnblogs.com/freewater/archive/2012/07/16/2593218.html 里有非常精简的代码

vector<int> factors;
void findFactor2(int sum,int n){
    if(sum<0||n<0)
        return ;
    if(sum==0){
        for(vector<int>::iterator iter=factors.begin();iter!=factors.end();++iter){
            cout<<*iter<<' ';
        }
        cout<<endl;
        return;
    }

    factors.push_back(n);//典型的01背包问题  
    findFactor2(sum-n,n-1);//放n,n-1个数填满sum-n 
    factors.pop_back();
    findFactor2(sum,n-1);//不放n,n-1个数填满sum   
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



猜您在找 Problem Description 有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数,现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程输出该平均值序列。 Input 输入数据有多组,每组占一行,包含两个正整数n和m,n和m的含义 Problem Description 有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。 Input 输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0标示输入数 阶乘因式分解(一) 给定两个数m,n,其中m是一个素数。 将n(0<=n<=10000)的阶乘分解质因数,求其中有多少个m。 输入第一行是一个整数s(0 【JAVA习题六】输入两个正整数m和n,求其最大公约数 输入正整数m和n,m 有n个整数,使其前面各数顺序向后移n-m个位置,最后m个数变成最前面的m个数 从键盘输入一个字符串,再输入两个正整数m和n,输出字符串中从m开始,连续n个字符。例如,输入abcdefg,2,3,输出bcd。 10.4 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数,见图。写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数。 有 n个整数,使其前面各数顺序向后移 m 个位置,最后m个数变成最前面的 m 个数。 Problem C: 指针:有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面m个数
 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM