acwing-168-生日蛋糕(剪枝+深搜)+codeforces-661-div3-D

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;
}

 

posted on 2020-08-07 22:02  mmn  阅读(158)  评论(0编辑  收藏  举报