华师一附中OI组
标题:
P1731 [NOI1999]生日蛋糕
[打印本页]
作者:
diggersun
时间:
2016-8-6 00:33
标题:
P1731 [NOI1999]生日蛋糕
https://www.luogu.org/problemnew/show/P1731
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为N*pi的M层生日蛋糕,每层都是一个圆柱体。 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。 令Q = S*pi 请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。(除Q外,以上所有数据皆为正整数)
每组数据两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为N*pi;第二行为M(M <= 20),表示蛋糕的层数为M。
输出仅一行,是一个正整数S(若无解则S=0)。
测试样例1
输入
100
2
输出
68
作者:
diggersun
时间:
2016-8-6 00:46
#include <iostream>
using namespace std;
int n,m;
int res=99999999;
bool check(int dep,int r,int h,int v,int s)
{
int maxv=0,mins=0,minv=0;
for(int i=1; i<=dep; ++i)
{
maxv+=(r-i)*(r-i)*(h-i);
mins+=2*i*i;
minv+=i*i*i;
}
return ((v+minv<=n)&&(v+maxv>=n)&&(s+mins<=res));
}
void dfs(int dep,int r,int h,int v,int s)
{
if(dep==0)
{
if(v==n) res=min(res,s);
}
else
if( check(dep,r,h,v,s) )
for(int nh=h-1; nh>=dep; --nh)
for(int nr=r-1; nr>=dep; --nr)
dfs(dep-1,nr,nh,v+nr*nr*nh,s+2*nr*nh);
}
int main()
{
cin>>n>>m;
for(int h=m; h<=n; h++)
for(int r=m; h*r*r<=n; ++r)
dfs(m-1,r,h,r*r*h,2*r*h+r*r);
if(res==9999999) res=0;
cout<<res;
return 0;
}
复制代码
作者:
lyc
时间:
2018-5-18 13:41
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m;
int minv[25], mins[25];
bool flag = 0;///是否有答案
int ans=0x3f3f3f3f;
void dfs(int now, int s, int v, int lr, int lh){
if(now == 0){
if(v == n) {
ans = min(ans, s);
flag = 1;
}
return ;
}
if(s + mins[now] > ans || v + minv[now] > n || s + 2*(n - v)/lr > ans) return ;
///面积的最优性剪枝;体积的可行性剪枝;
for(int r=lr-1; r>=now; r--){
if(now == m) s = r*r;///俯视图圆的面积在第一次搜索时加上
int uph = min((n-v-minv[now-1])/(r*r), lh - 1);
for(int h=uph; h>=now; h--)
{
dfs(now - 1, s+2*r*h, v+r*r*h, r, h);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=m; i++)
{
minv[i] = minv[i-1] + i*i*i;
mins[i] = mins[i-1] + i*i*2;
}
dfs(m, 0, 0, sqrt(n), 28);///20000开三次方开始搜
if(flag){
cout<<ans;
return 0;
}
cout<<0;
return 0;
}
复制代码
作者:
胡雨菲菲
时间:
2018-6-7 15:03
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N2 = 20, INF = 0x7f7f7f7f;
int N, M, ans = INF, mins[N2], minv[N2];
void DFS(int d, int s, int v, int lastR, int lastH) {
if(!d) {
if(v == N) {
ans = min(ans, s);
}
return;
}
for(int R = min(lastR - 1, (int)(sqrt(N - v))); R >= d; R--) {
/*if((2 * (N - v)) / R + s >= ans) { /// WA
continue;
}*/
if(d == M) {
s = R * R;
}
for(int H = min(lastH - 1, (N - v) / (R * R)); H >= d; H--) {
int v2 = v + R * R * H;
int s2 = s + 2 * R * H;
if((2 * (N - v2)) / R + s2 >= ans) {
continue;
}
if(s2 + mins[d - 1] >= ans) {
continue;
}
if(v2 + minv[d - 1] > N) {
continue;
}
DFS(d - 1, s2, v2, R, H);
}
}
return;
}
void init(int n) {
for(int i = 1; i <= n; i++) {
mins[i] = mins[i - 1] + 2 * i * i;
minv[i] = minv[i - 1] + i * i * i;
}
return;
}
int main() {
scanf("%d%d", &N, &M);
init(M);
DFS(M, 0, 0, INF, INF);
printf("%d", (ans == INF) ? 0 : ans);
return 0;
}
复制代码
作者:
张笑宇
时间:
2018-7-4 19:01
#include<iostream>
#include<cmath>
using namespace std;
int m,n,ans=999999;
const int mx=50;
int mins[mx],minv[mx];
void dfs(int i,int sums,int sumv,int r,int h)///第i层 表面积sums
{
if (sums+mins[i]>ans) return;
else if (sumv+minv[i]>n) return;
else if (sums+2*(n-sumv)/r>ans) return;
///三个判断
if (i<=0)
{
if (sumv==n)
ans=min(ans,sums);
return;
}
else
{
for (int ir=r-1; ir>=i; ir--)
for (int ih=h-1; ih>=i; ih--)
{
int sums0=2*ih*ir;
if (i==m) sums0+=ir*ir;
dfs(i-1,sums+sums0,sumv+ir*ir*ih,ir,ih);
}
}
}
int main()
{
cin>>n>>m;///nπ体积 m层
for (int i=1; i<=m; i++)
{
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
dfs(m,0,0,sqrt(n),n);
if (ans==999999) cout<<"0";
else cout<<ans;
return 0;
}
复制代码
作者:
universehyf
时间:
2018-11-18 11:54
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define FOR(i,a,b) for(register int i(a);i<=b;++i)
#define For(i,a,b) for(register int i(a);i>=b;--i)
int mins[20],minv[20];
int ans=1<<30,s;
bool prune(int maxh,int maxr,int n,int v)
{
int cc=0;
FOR(i,0,n-1) cc+=(maxh-i)*(maxr-i)*(maxr-i);
if(cc<v) return 1;
else return 0;
}
void dfs(int maxh,int maxr,int n,int v,int m)
{
if(n==0)
{
if(v) return;
ans=min(ans,s);
}
if(s+mins[n]>ans) return;
if(maxh<n||maxr<n) return;
if(minv[n]>v) return;
if(prune(maxh,maxr,n,v)) return;
For(i,maxr,n)
{
if(n==m) s=i*i;
For(j,maxh,n)
{
s+=2*i*j;
dfs(j-1,i-1,n-1,v-i*i*j,m);
s-=2*i*j;
}
}
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
FOR(i,1,m)
mins[i]=mins[i-1]+2*i*i,
minv[i]=minv[i-1]+i*i*i;
if(n<minv[m]) printf("0");
else
{
int maxh=(n-minv[m-1])/(m*m)+1;
int maxr=sqrt((n-minv[m-1])/m)+1;
dfs(maxh,maxr,m,n,m);
if(ans==1<<30) printf("0");
else printf("%d",ans);
}
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2