POJ1190:生日蛋糕

11 篇文章 0 订阅

这道题减枝的要求很高。

首先很重要的一点是遍历的顺序。

  建议蛋糕r和h从大到小遍历。因为这道题如果超时,肯定遍历的数据量太大。

直观的,数据量小的时候,当r和h从小到大遍历的更快。当数据量很大,r和h从大到小遍历就更快了。数据量小的时候不可能TLE的,所以r和h从大到小遍历。

  既然r和h从大到小遍历,最底层的最大r和h是很好确定的。自然,从蛋糕的底层到顶层遍历最为方便。

蛋糕的总表面积计算 = 所有圆柱体的侧面积 + 最底层蛋糕的底面面积

减枝思路:

1.当前体积 > 蛋糕总体积,return

2.当前表面积 > 最小总表面积,return

3.当剩余的体积 > 最大可以消耗的体积,return

4.当前表面积 + 最小剩余表面积(即剩下所有圆柱的侧面积之和) > 最小总表面积,return

  由于圆柱的r越大,侧面积越小。所以最小剩余表面积可以想象为:剩余体积全部形成一个当前允许的最大半径的一个圆柱。这个圆柱的侧面积为当前最小剩余表面积。

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;

int n, m, mins = INT_MAX;
int sumv = 0, sums = 0;
int flag = 0;
int dfs(int curl, int curr, int curh)
{
	if (sumv > n)//1
		return 0;
	if (sums > mins)//2
		return 0;
	if (n - sumv > (m - curl) * (curr - 1) * (curr - 1) * (curh - 1))//3
		return 0;
	if (sums + 2 * (n - sumv) / curr > mins)//4  16ms,去掉减枝4,125ms
		return 0;
	if (curl == m)
	{
		if (sumv == n)
		{
			mins = sums;
			flag = 1;
			return 0;
		}
		else
			return 0;
	}

	for (int r = curr - 1; r >= m - curl; r--)//r
	{
		flag = 0;
		for (int h = curh - 1; h >= m - curl; h--)//h
		{
			if (curl == 0)
				sums += r * r;
			sums += 2 * r * h;
			sumv += r * r * h;
			dfs(curl + 1, r, h);
			sumv -= r * r * h;
			if (curl == 0)
				sums -= r * r;
			sums -= 2 * r * h;
		}
	}
	return 0;
}

int main()
{
	cin >> n >> m;
	int resv = n;
	for (int i = 1; i < m; i++)
		resv -= i * i * i;
	double maxr = sqrt(double(resv / m));
	double maxh = resv / m * m;
	dfs(0, maxr, maxh);
	cout << mins << endl;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值