acwing-168-生日蛋糕(剪枝)
题意:给定m层蛋糕的最大体积n,如何使表面积最小
解:暴搜,顺序即为按从下到上的蛋糕层数,或者从上到下的蛋糕层数
剪枝:
1,优化搜索顺序,所以就从下到上进行搜索。
每一层枚举高度和半径,按照递减顺序来枚举。块数约大,决策越少;
dfs状态,当前枚举到哪一层,当前的体积,当前的面积(r,和h有范围)dfs(dep,v,s);
2,r,h从大到小枚举。
当前体积为v,则剩下体积n-v
表面积(此题可以忽略π),r*r*h,h=1,r最大,r最大√n-v,r有限制,
每次r的值 depth<=r<=min(√n-v,R[depth+1]-1)
每次h的值 depth<=h<=min( (n-v)/r^2 , H[depth+1] -1) (n-v)/r^2向下取整
3,dep层的minv(dep)+v>n直接return掉。
或者mins(dep)+s>ans,直接return。
minv和mins直接取极限
4,n-v=∑i=1,dep (ri^2*hi)
Sdep=∑i=1,dep(2*ri*hi)
=2/r(dep+1)* ∑ri*hi*r(dep+1)>=2/r(dep+1)* ∑ri*ri*hi=2(n-v)/r(dep+1)
则当前Sdep>=2(n-v)/r(dep+1)
即s+sdep>=ans,直接return。
代码:
#include<bits/stdc++.h> const int maxn=30; const int inf=0x3f3f3f3f; typedef long long ll; using namespace std; int n,m; int minv[maxn],mins[maxn]; int R[maxn],H[maxn]; int ans=inf; void dfs(int dep,int v,int s) { if(v+minv[dep]>n) return ; if(s+mins[dep]>=ans) return ; if(s+2*(n-v)/R[dep+1]>=ans) return ;//3个剪枝 if(!dep)//搜索到最后一层 { if(v==n) ans=s; return ; } for(int i=min(R[dep+1]-1,(int)sqrt(n-v)); i>=dep; i--)//从当前限制开始进行枚举 { for(int j=min(H[dep+1]-1,(n-v)/i/i); j>=dep; j--) { int t=0; if(dep==m) t=i*i;//最后一层,加上圆的面积 R[dep]=i; H[dep]=j;//每次更新,为0时会出现错误 dfs(dep-1, v+i*i*j,s+2*i*j+t);//继续搜索 } } } int main() { cin>>n>>m; for(int i=1; i<=m; i++)//初始化v和s,极限化,第一层1,第二层2... { minv[i]=minv[i-1]+i*i*i; mins[i]=mins[i-1]+2*i*i; } R[m+1]=H[m+1]=inf; dfs(m,0,0); if(ans==inf) ans=0; cout<<ans<<endl; return 0; }
codeforces-661-div3-D
题意:01串,找最小子序列使得01间隔开来
解:栈模拟,对于每一个序列,记录下最后一个1和0 的位置,然后对于第i个位置,如果是0,就和上一个1同序列,如果是1就和上一个0同序列;
栈模拟,时间复杂度O(N);
代码:
#include<bits/stdc++.h>
const int maxn=30;
const int inf=0x3f3f3f3f;
typedef long long ll;
using namespace std;
int t;
void solve()
{
int n;
cin>>n;
string s;
cin>>s;
stack<int> st1,st2;//st1存0,st2存1
vector<int> ans(n,0);
int ma =0;
for(int i=0; i<n; i++)
{
if(s[i]=='0')//当前为0
{
if(!st2.empty())//存1的栈不为空
{
ans[i]=ans[st2.top()];//寻找上个1的位置
st2.pop();
st1.push(i);
}
else
{
ans[i]=st1.size()+1;
st1.push(i);
}
}
else
{
if(!st1.empty())
{
ans[i]=ans[st1.top()];
st1.pop();
st2.push(i);
}
else
{
ans[i]=st2.size()+1;
st2.push(i);
}
}
ma=max(ma,ans[i]);
}
cout<<ma<<endl;
cout<<ans[0];
for(int i=1; i<n; i++) cout<<" "<<ans[i];
cout<<endl;
}
int main()
{
cin>>t;
while(t--)
solve();
system("pause");
return 0;
}