淘宝实习生 笔试算法题 装鸡蛋
2011-04-01 13:34
211 查看
转自:http://blog.csdn.net/Jason20075563/archive/2011/03/30/6289267.aspx
1 1 1 1 1 1 1 1 2 10
1 1 1 1 1 1 1 1 3 9
1 1 1 1 1 1 1 1 4 8
1 1 1 1 1 1 1 1 5 7
1 1 1 1 1 1 1 1 6 6
1 1 1 1 1 1 1 2 2 9
1 1 1 1 1 1 1 2 3 8
1 1 1 1 1 1 1 2 4 7
1 1 1 1 1 1 1 2 5 6
1 1 1 1 1 1 1 3 3 7
1 1 1 1 1 1 1 3 4 6
1 1 1 1 1 1 1 3 5 5
1 1 1 1 1 1 1 4 4 5
1 1 1 1 1 1 2 2 2 8
1 1 1 1 1 1 2 2 3 7
1 1 1 1 1 1 2 2 4 6
1 1 1 1 1 1 2 2 5 5
1 1 1 1 1 1 2 3 3 6
1 1 1 1 1 1 2 3 4 5
1 1 1 1 1 1 2 4 4 4
1 1 1 1 1 1 3 3 3 5
1 1 1 1 1 1 3 3 4 4
1 1 1 1 1 2 2 2 2 7
1 1 1 1 1 2 2 2 3 6
1 1 1 1 1 2 2 2 4 5
1 1 1 1 1 2 2 3 3 5
1 1 1 1 1 2 2 3 4 4
1 1 1 1 1 2 3 3 3 4
1 1 1 1 1 3 3 3 3 3
1 1 1 1 2 2 2 2 2 6
1 1 1 1 2 2 2 2 3 5
1 1 1 1 2 2 2 2 4 4
1 1 1 1 2 2 2 3 3 4
1 1 1 1 2 2 3 3 3 3
1 1 1 2 2 2 2 2 2 5
1 1 1 2 2 2 2 2 3 4
1 1 1 2 2 2 2 3 3 3
1 1 2 2 2 2 2 2 2 4
1 1 2 2 2 2 2 2 3 3
1 2 2 2 2 2 2 2 2 3
可能情况的数量:40
在网上看到的第一批笔试里面的一个算法编程题。
问题:有N个蛋和M个篮子,把蛋放到M个篮子里,每个篮子都不能为空。另外,需要满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到。写出程序,使得输入一个(N,M),输出所有可能的分配情况。
自己写了一个下,纯暴力,几乎没剪枝。
当n为20,m为10的时候,结果是40中情况。
codes:
结果:1 1 1 1 1 1 1 1 2 10
1 1 1 1 1 1 1 1 3 9
1 1 1 1 1 1 1 1 4 8
1 1 1 1 1 1 1 1 5 7
1 1 1 1 1 1 1 1 6 6
1 1 1 1 1 1 1 2 2 9
1 1 1 1 1 1 1 2 3 8
1 1 1 1 1 1 1 2 4 7
1 1 1 1 1 1 1 2 5 6
1 1 1 1 1 1 1 3 3 7
1 1 1 1 1 1 1 3 4 6
1 1 1 1 1 1 1 3 5 5
1 1 1 1 1 1 1 4 4 5
1 1 1 1 1 1 2 2 2 8
1 1 1 1 1 1 2 2 3 7
1 1 1 1 1 1 2 2 4 6
1 1 1 1 1 1 2 2 5 5
1 1 1 1 1 1 2 3 3 6
1 1 1 1 1 1 2 3 4 5
1 1 1 1 1 1 2 4 4 4
1 1 1 1 1 1 3 3 3 5
1 1 1 1 1 1 3 3 4 4
1 1 1 1 1 2 2 2 2 7
1 1 1 1 1 2 2 2 3 6
1 1 1 1 1 2 2 2 4 5
#include "stdafx.h" #include<iostream> #include<math.h> #include<malloc.h> #include<fstream> using namespace std; struct solution { int *ptr; struct solution *next; }; typedef struct solution solu; int* first(int n,int m); //计算出第一种组合 solu* others(int n,int m,solu *head,solu *prior); //计算出其他组合 int sum(int n,int *p); //计算前n-1个篮子里的蛋数和 bool only(solu *head,int *p,int m); //检查组和是否满足要求 int ways; //全局变量,保存组合的方法数 void main() { int n=0,m=0,i=0,k=0; solu *head=NULL; solu *temp=NULL; LABLE: cout<<"输入鸡蛋数N="; cin>>n; cout<<"输入篮子数M="; cin>>m; if(m<=0||n<=0||m>n||(double)n>=pow(2.0,m)) //对m,n的约束 { cout<<"输入不合法!"<<endl; goto LABLE; } cout<<"正在计算..."<<endl; head=others(n,m,head,NULL); //调用others开始计算 temp=head; ofstream file("D://egg.txt"); //结果保存着这个目录下 cout<<"共有"<<ways<<"种组合方式:"<<endl; file<<"共有"<<ways<<"种组合方式:"<<endl; k=ways; while(temp!=NULL&&ways) { cout<<"方式"<<k-ways+1<<":"<<endl; file<<"方式"<<k-ways+1<<":"<<endl; for(i=0;i<m;i++) { cout<<*(temp->ptr+i)<<" "; file<<*(temp->ptr+i)<<" "; } delete[] temp->ptr; temp=temp->next; cout<<endl; file<<endl; ways--; } file.close(); cout<<"操作结果保存在D://egg.txt,您可以查看或删除之。"; cin>>i; } int sum(int n,int *p) //计算前n-1个篮子里的总蛋数 { int total=0; for(int i=0;i<n;i++) { total+=*(p+i); } return total; } int* first(int n,int m) { int *p,i=0,temp1=0,temp2=0; p=(int *)malloc(m*sizeof(int)); for(i=0;i<m;i++) //每个篮子里放一个蛋 { *(p+i)=1; } //下面的分配满足的条件: //“总能找到几个篮子,使里面鸡蛋的和等于任意一个小于n的正整数” //下面的if~else语句完成一种组合,升序排列,并使后面的篮里的蛋尽量多 if(n-m>m-1) //剩下的蛋数大于前面m-1个篮子里的蛋数和, { *(p+m-1)+=m-1; while(sum(m,p)<n) //还有蛋剩余 { temp1=n-sum(m,p); //剩蛋数 for(i=m;i>0;) { temp2=sum(i-1,p); //第i个篮子前面的所有篮子里的蛋数的总和 if(*(p+i-1)<=temp2) //第i个篮子里的蛋数小于等于前面篮子里蛋的总数,给这个篮里加蛋 //否则,见else { if(temp1<=temp2-*(p+i-1)+1) //剩下的蛋可以全部放到第i个篮里,完毕 {*(p+i-1)+=temp1;break;} else {*(p+i-1)+=temp2-*(p+i-1)+1;break;} //在第i个篮子放可能达到的最多蛋数 } else i--; //检测前面那个篮子 } } } else *(p+m-1)+=n-m; //剩下的蛋数小于等于前面m-1个篮子里的蛋数和, //把所有的蛋都放到最后一个篮里,完成一种组合。 return p; } solu* others(int n,int m,solu* head,solu *prior) { int i=0,j=0,k=0; if(head==NULL) //还没有任何组合 { solu *s=new(solu); s->ptr=first(n,m); //调用first()生成满足后面的值最大的升序序列 head=s; head->next=NULL; prior=head; ways=1; } for(j=m-1;j>0;j--) //两重循环,开始计算其他组合 //原理是从后面的篮子里取出鸡蛋放入前面的篮子中 { if(*(prior->ptr+j)==1) //后面的篮子里蛋数为1,跳出循环 break; for(i=j-1;i>0;i--) //一个个往前挨 { if(*(prior->ptr+j)-1>*(prior->ptr+i)) //后面的篮子减掉后不能比前面的少,保持升序排列 { int *p=(int *)malloc(m*sizeof(int)); for(k=0;k<m;k++) { (*(p+k))=(*(prior->ptr+k)); } (*(p+j))--;(*(p+i))++; if(only(head,p,m)) //检查是否满足条件,满足则将结果添加到链表中 { solu *stemp=new(solu); stemp->ptr=p; stemp->next=head->next;head->next=stemp; head=others(n,m,head,stemp); ways++; } else delete[] p; } else if(*(prior->ptr+j)-1==*(prior->ptr+i)) continue; else break; } } return head; } bool only(solu *head,int *p,int m) //判断条件是否符合 { solu *s=head; int flag=0,i=0; for(int k=0;k<m-1;k++) { if(*(p+k+1)<*(p+k)||*(p+k+1)>sum(k+1,p)+1) //两个条件:1、升序,2、后面的数必须小于等于前面的篮子总数和加1 return false; } while(s!=NULL) //判断是否有过相同的组合,有则返回false { flag=0; for(i=0;i<m;i++) { if(*(s->ptr+i)!=*(p+i)) { flag=1; break; } } if(!flag) { return false; } s=s->next; } return true; //检查通过,返回true }
1 1 1 1 1 2 2 3 3 5
1 1 1 1 1 2 2 3 4 4
1 1 1 1 1 2 3 3 3 4
1 1 1 1 1 3 3 3 3 3
1 1 1 1 2 2 2 2 2 6
1 1 1 1 2 2 2 2 3 5
1 1 1 1 2 2 2 2 4 4
1 1 1 1 2 2 2 3 3 4
1 1 1 1 2 2 3 3 3 3
1 1 1 2 2 2 2 2 2 5
1 1 1 2 2 2 2 2 3 4
1 1 1 2 2 2 2 3 3 3
1 1 2 2 2 2 2 2 2 4
1 1 2 2 2 2 2 2 3 3
1 2 2 2 2 2 2 2 2 3
可能情况的数量:40
相关文章推荐
- 淘宝实习生 笔试算法题 装鸡蛋
- 微软的实习生笔试题,不是太难,算法的题好多,但是很多答案都不确定,欢迎大家讨论答案~
- 数字字符串一道有道实习生笔试算法题分析
- 阿里巴巴2013实习生笔试题精选2道算法题
- 阿里巴巴2015算法工程师实习生笔试卷
- 算法面试题-今日头条2017客户端工程师实习生笔试题4:或与加
- 微软的实习生笔试题,不是太难,算法的题好多,但是很多答案都不确定,欢迎大家讨论答案~
- 2011淘宝春季实习生招聘笔试题
- 算法最小2013-5-5阿里巴巴实习生部分笔试题
- 【白话经典算法系列之十四】腾讯2012年实习生笔试加分题 .
- 2016京东算法工程师实习生笔试编程题:上台阶
- 【面试笔试算法】Problem 1 : DP滑雪问题--网易互联网算法实习生2017笔试题
- 在一个元素个数为N的数组里,找到升序排在N/5位置的元素的最优算法时间复杂度是----阿里巴巴2015实习生笔试题
- 【笔试面试题】腾讯2013实习生面试算法题及参考答案
- 【面试笔试算法】Problem 1 : DP滑雪问题--网易互联网算法实习生2017笔试题
- 2016京东算法工程师实习生笔试编程题:小球的距离
- 【笔试面试题】腾讯2013实习生面试算法题及参考答案
- 阿里算法实习生笔试——墙之间积水体积
- 阿里巴巴2013实习生笔试题精选2道算法题
- 淘宝2011春季实习生笔试题