【100题】第二十一题(中兴面试题)

一,题目:输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来。

二,解释:比如输入m=4 n=4 则输出为:4

1+3 而2+2不正确,因为重复输出数字了

中心思想:1)如果1+2+3+……+n<m 则不存在这个数

2)如果m<n 则应该让n=m //因为m--->n之间的数都已经大于m了 没必要再计算了

3)如果m=n 输出n

4)如果m>n 递归循环

源码采用原型:0-1背包问题

参考博客:http://blog.csdn.net/tianshuai11/article/details/7025464

三,源码:(类似源码五)

#include<list>

#include<iostream> using namespace std; list<int> list1; void find_factor(int sum, int n) { // 递归出口 if(n <= 0 || sum <= 0) return; // 输出找到的结果 if(sum == n) { // 反转list list1.reverse(); for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++) cout << *iter << " + "; cout << n << endl; list1.reverse(); } list1.push_front(n); //典型的01背包问题 find_factor(sum-n, n-1); //放n,n-1个数填满sum-n list1.pop_front(); find_factor(sum, n-1); //不放n,n-1个数填满sum } int main() { int sum, n; cout << "请输入你要等于多少的数值sum:" << endl; cin >> sum; cout << "请输入你要从1.....n数列中取值的n:" << endl; cin >> n; cout << "所有可能的序列,如下:" << endl; find_factor(sum,n); return 0; }


四,源码(java方法)

/** * 输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 使其和等于 m ,要求将其中所有的可能组合列出来. e.g n=6,m=6 1,2,3 2,4 1,5 n= * @author wangxm */ public class Comp { static void getAllComp(int n,int m){ String pre = m+"="; int theMax = (1+n)*n/2; if(theMax<m){ System.out.println("不存在该数!"); }else{ for(int i=1;i<=m/2;i++){ //从1开始计数,打印出两个数的组合,并且两数不相等 if(i != m-i) System.out.println(pre+i+"+"+(m-i)); //调用递归,继续求得大于2个数的组合 getTheResult(m-i,pre+i,i); } } } //调用递归,继续求得大于2个数的组合,j为组合中已用过的数,所以取大于该数的。 static void getTheResult(int m,String pre,int j){ for(int i=j+1;i<=m/2;i++){ if(i != m-i) System.out.println(pre+"+"+i+"+"+(m-i)); getTheResult(m-i,pre+"+"+i,i); } } public static void main(String[] args) { getAllComp(3,6); } } 五,源码(容易理解)

#include <iostream> using namespace std; int length; void PrintSolution(int *flag) { for (int i=0;i<length;i++) { if (flag[i]==1) { cout<<i+1<<" "; } } cout<<endl; } void BagProblem(int m,int n, int *flag) { if (n<1||m<1) return; if (m<n) n=m; if (n==m) { flag[n-1]=1; PrintSolution(flag); flag[n-1]=0; } flag[n-1]=1; //n先放入背包中 BagProblem(m-n,n-1,flag); //剩余空间为 m-n 可以取的背包为 1->n-1 flag[n-1]=0; //n不放入背包中 BagProblem(m,n-1,flag); //剩余空间为 m 可以取的背包为 1->n-1 } int main() { int m,n; cout<<"please input m and n:"<<endl; cin>>m>>n; cout<<"the solution is :"<<endl; length=n; int *flag=(int *)malloc(sizeof(int)*n); memset(flag,0,sizeof(int)*n);//注意memset用法及区分sizeof(flag)/sizeof(int)*n BagProblem(m,n,flag); free(flag); return 0; }

【0-1背包公式】opt[i][v] = max(opt[i-1][v] , opt[i-1][v-c[i]] + w[i])
解释如下:
opt[i-1][v] 表示第i件物品不装入背包中,而opt[i-1][v-c[i]] + w[i] 表示第i件物品装入背包中。

对应之后:n为物品 m为背包容积,这里相当于求“所有可能的装满的装法”。忽略了价值的计算即没有真正计算出那种装法最佳



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值