把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?注意:如果有7个苹果和3个盘子,(5,1,1)和(1,5,1)被视为是同一种分法。
7个苹果和3个盘子,有三种情况:
- 7个苹果全放进1个盘子里:(7)
- 7个苹果全放进2个盘子里:(1,6),(2,5),(3,4)
- 7个苹果全放进3个盘子里:(1,1,5),(1,2,4),(1,3,3),(2,2,3)
针对第三种情况,观察规律,只有分苹果的序列是非减序列,能够保证分法不重复。数学语言,针对分法(a,b,c),当c>=b>=a时,可以保证形成的序列不重复。
我的代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution{
public:
int placeApple(int apples,int plates){
if(0==plates){return 0;}
if(1==plates){return 1;}
if(apples==plates){return 1;}
int half=apples/2;
m_eff=0;
if(2==plates) {return half;}
std::vector<uint8_t> states;
states.resize(plates,0);
for(int i=1;i<=half;i++){
states.at(0)=i;
recursion(states,apples-i,0);
}
return m_eff;
}
private:
void recursion(std::vector<uint8_t>& states,int apples,int n){
if(n==states.size()-2){
if(apples>=states.at(n)){
states.at(n+1)=apples;
m_eff++;
/*for(int i=0;i<states.size();i++){
std::cout<<(uint32_t)states.at(i)<<" ";
}
std::cout<<std::endl;*/
}
return;
}
int half=apples/2;
if(half>=states.at(n)){
for(int i=states.at(n);i<=half;i++){
states.at(n+1)=i;
recursion(states,apples-i,n+1);
}
}
return;
}
int m_eff=0;
};
int main(){
Solution so;
int apples=5,plates=5;
std::cin>>apples;
std::cin>>plates;
if(apples<plates){
plates=apples;
}
int ret=0;
for(int i=1;i<=plates;i++){
ret+=so.placeApple(apples,i);
}
std::cout<<ret<<std::endl;
}
网友评论