很有幸地发现了洛谷的大牛分站,看到里面东西都奇奇怪怪的,觉得特别神奇,于是点了个随机跳题,就这样来到了一个号称“提高+,省选”难度的题(⊙o⊙)…
接下来看题目
P1731 生日蛋糕
题目背景
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层
生日蛋糕,每层都是一个圆柱体。
设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i
for(int i=1;i<=m;i++){
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
于是忽然领悟自己一开始之所以不会搜是因为没有注意到整数二字的猥琐性(⊙o⊙)…
便自己写了一个深搜
void dfs(int sumv,int sums,int r,int h,int pos)
{
if(pos==0)
{
if(sumv==n)
ans=gsmin(sums,ans);
return;
}
if(sumv+minv[pos]>n)return;//体积超值
if(sums+mins[pos]>ans)return;//面积已经不最小
if(2*(n-sumv)/r+sums>=ans)return;//之后都取最小结果比ans大
for(int i=r-1;i>=pos;i--)
{//用循环挨个搜索上一层的半径 i
if(pos==m) sums=i*i;
//如果是第一层,sums=0,需要来个初始值
int temp=gsmin((n-minv[pos-1]-sumv)/i/i,h-1);
//上一层高度最小值temp
for(int j=temp;j>=pos;j--)//上一层高度 j
dfs(sumv+i*i*j,sums+2*i*j,i,j,pos-1);
}
}
诶…?加个主函数就给过了!
哇,我好棒棒!
【hh,然而并没有,,,,,一开始dfs最后地推的时候i和j写反了…….
嗯,那就把完整代码附上:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,s,ans=0x3f3f3f3f;
int minv[25],mins[25];
int gsmin(int a,int b);
void dfs(int sumv,int sums,int r,int h,int pos)
{
if(pos==0)
{
if(sumv==n)
ans=gsmin(sums,ans);
return;
}
if(sumv+minv[pos]>n)return;//体积超值
if(sums+mins[pos]>ans)return;//面积已经不最小
if(2*(n-sumv)/r+sums>=ans)return;//之后都取最小结果比ans大
for(int i=r-1;i>=pos;i--)
{//用循环挨个搜索上一层的半径 i
if(pos==m) sums=i*i;
//如果是第一层,sums=0,需要来个初始值
int temp=gsmin((n-minv[pos-1]-sumv)/i/i,h-1);
//上一层高度最小值temp
for(int j=temp;j>=pos;j--)//上一层高度 j
dfs(sumv+i*i*j,sums+2*i*j,i,j,pos-1);
}
}
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]+2*i*i;
}
dfs(0,0,n+1,n+1,m);
cout<<ans;
}
int gsmin(int a,int b)
{
if(a<b) return a;
else return b;
}