洛谷 P1731 [NOI1999] 生日蛋糕

Description

P1731 [NOI1999] 生日蛋糕

Solution

明显的就是搜索(但是我一点都不会写,我好蒻啊)。

首先一定是从下往上搜,如果从上往下的话就没有上界了,容易一搜到底。

然后再考虑这么几个优化:

  • 当前体积 \(> \ n\),返回。

  • 当前层数 \(> \ m\),返回。

  • 当前面积 \(\geq\) 已经搜到的最大面积,返回。

  • 当前体积 \(+\) 之后的最大体积 \(< \ n\),返回。

  • 当前表面积 \(+\) 之后最大表面积 \(\geq\) 已经搜到的答案,直接返回(emm……有了这条前面那个好像就不用了,算了不管了)。

\(dfs\) 时,记录一下当前层数,剩余体积,当前侧面积

半径,高度的枚举,从上一层的半径,高度开始,一直到还需要的层数即可,每层都留一个 1.

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f

using namespace std;

int n, m, ans = INF;
int r[30], h[30];

inline void dfs(int x, int v, int res){//x:层数  v:剩余体积  res:当前表面积
	int tmp = m - x + 1;//还需要多少层
	if(v < 0 || x > m + 1 || res >= ans) return;
	if(!v && x == m + 1){
		res += r[1] * r[1];
		ans = min(ans, res);
		return;
	}
	if(res + tmp + r[1] * h[1] > ans) return;
	if(v - r[x - 1] * r[x - 1] * h[x - 1] * tmp > 0) return;
	for(int i = r[x - 1] - 1; i >= tmp; i--){
		for(int j = h[x - 1] - 1; j >= tmp; j--){
			if(v - i * i * j >= 0 && x <= m){
				r[x] = i, h[x] = j;
				dfs(x + 1, v - i * i * j, res + (2 * i * j));
				r[x] = h[x] = 0;
			}
		}
	}
}

int main(){
	scanf("%d%d", &n, &m);
	r[0] = h[0] = (int)sqrt(n);
	dfs(1, n, 0);
	printf("%d\n", ans == INF ? 0 : ans);
	return 0;
}

End

posted @ 2021-10-08 11:46  xixike  阅读(62)  评论(0编辑  收藏  举报