zoukankan      html  css  js  c++  java
  • DFS+剪枝:N个蛋放入M个篮子并可以任意取

    淘宝笔试题:

         有N个蛋和M个篮子,把蛋放到M个篮子里,每个篮子都不能为空。另外,需要满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到。写出程序,使得输入一个(N,M),输出所有可能的分配情况

    #include "StdAfx.h"
    #include <iostream>
    #include <math.h>
    using namespace std;
    #define MAX 1000
    int ans[MAX];
    int count = 0;
    int cal = 0;
    //如果前x的篮子已经放了y个鸡蛋,则第x+1个篮子可以放1到y+1个鸡蛋,(如果放y+2,则取不出y+1)
    //第x+2个篮子可以放(y+y+1)+1=2y+2
    //第x+3个篮子可以放(2y+2+y+1+y)+1=4y+4,这样我们可以从0开始 ,依次开始遍历所有存放情况
    void dfs(int hasEgg,int nextBasketIndex,int totalEgg,int totalBasket,int last){
    
    	
    
    	if(hasEgg==totalEgg && nextBasketIndex==totalBasket){
    
    
    		for(int i=0;i<totalBasket;i++){
    
    			printf("%d ",ans[i]);
    			
    		}
    		printf("\n");
    		count++;
    		return ;
    	}
    	if(nextBasketIndex>=totalBasket||hasEgg>=totalEgg){
    					
    				return;
    	}
    	//剪枝1:如果后面的所有篮子都用最小数来填充 都比总数大
    	if(hasEgg+last*(totalBasket-nextBasketIndex)>totalEgg)return;
    	//剪枝2:如果后面的所有篮子都用最大数来填充 还是不够大
    	if((hasEgg+1)*(pow(2,totalBasket-nextBasketIndex)-1)+hasEgg<totalEgg)return;
    	for(int i=last;i<=hasEgg+1;i++){
    
    		ans[nextBasketIndex] = i;
    		cal++;
    		
    		dfs(hasEgg+i,nextBasketIndex+1,totalEgg,totalBasket,i);
    	}
    
    }
    int solve(int egg,int basket){
    
    	if(egg>pow(2,basket)||basket>egg)
    		return 0;
    	dfs(0,0,egg,basket,1);
    	return count;
    	
    }
    void main(){
    
    	solve(16,10);
    	printf("结果:%d\n运算次数:%d\n",count,cal);
    }
  • 相关阅读:
    待你长发及腰
    《线段树》讲稿
    Codeforces #Round 376 F 题解
    包裹快递 题解
    Codeforces #Round 376 部分题解
    圆圈舞蹈 题解
    奶牛晒衣服 题解
    BZOJ 1034 题解
    BZOJ 1045 题解
    BZOJ 1054 题解
  • 原文地址:https://www.cnblogs.com/yangyh/p/2162243.html
Copyright © 2011-2022 走看看