poj 1190 生日蛋糕【重要枝剪】

生日蛋糕

Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 26207 Accepted: 9342
Description

7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
Input

有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output

仅一行,是一个正整数S(若无解则S = 0)。
Sample Input

100
2
Sample Output

68

圆柱公式
体积V = πR2H
侧面积A’ = 2πRH
底面积A = πR2

枝剪的情况

  1. 当前的体积加上该层的上面的最小体积比总体积大,就枝剪。
    v + minV[m - 1] > N
  2. 当前的表面积加上该层以上的最小表面积比当前的最优解大,这次的搜索就结束
    s + minS[m-1] > ans
  3. 从下往上搜索, 所以知道第m层的体积和表面积, 剩余的体积是: left = N - v
    假设上面的是只有一个圆柱, s侧面 = 2 * PI * r * h = 2 * (N - v) / r
    and (v = pi * r * r * h)
    如果 s侧面 + s >= ans 剪枝
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
using namespace std;
int N, M;
int minx = 0x3fff;
int minV[25];
int ans; // 最优解 
int minS[25];
void dfs(int m, int v, int s, int r, int  h){//从下面的一层开始往上面搜索 
		if(m == 0){											//	m 当前层数, v 当前的体积, s当前的表面积 r 当前层的半径  h 当前层的高 
			if( v == N && s < ans ){
				ans = s;
			}
			return ;
		}
		if(v + minV[m - 1] > N || s + minS[m - 1] > ans || 2 * (N - v) / r + s >= ans) return; //剪枝
		for(int i = r - 1; i >= m; i--){ //按照递减序列枚举第m层的所有可能值 
			if(m == M) s = i * i;//当前层是m层的时候, 他的半径是整个蛋糕的上表面积, 再加上侧面积, 这里这样 以后就只需要加侧面积了 
			int max_h = min((N - v - minV[m-1])/(i*i), h - 1);// 第m层的最大体积的高度 
			// N-v该层下面层的体积, minV[m-1](该层上面层的最小体积) i*i 当前层的面积 i 是当前层的半径
			for(int j = max_h; j >= m; j--){
				dfs(m - 1, v + i * i * j, s + 2 * i * j, i, j );
			} 
		} 
		
}
int main(){
 	minV[0] = 0;
 	minS[0] = 0;
 	for(int i = 1; i <= 20; i++){//体积和表面积最小的时候就是 最上面的一层 r = h = 1;  接着就是下面的一层 r = h = 2; 
 		minV[i] = minV[i - 1] + i * i * i;
 		minS[i] = minS[i - 1] + 2 * i * i;
	 }
	while(~scanf("%d%d", &N, &M)){
		ans = 0x3fff;
		dfs(M, 0, 0, N + 1, N + 1);//蛋糕的总体积是n,所以他的半径和高再大也不可能大于n;所以从n开始深搜
		if(ans == 0x3fff)  printf("0\n");
		else 
		printf("%d\n", ans); 
	}
	return 0;
}


代码

发布了28 篇原创文章 · 获赞 22 · 访问量 1042

猜你喜欢

转载自blog.csdn.net/qq_45432665/article/details/103209009
今日推荐