zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    python数据类型:字典Dictionary
    python数据类型:元组
    python数据类型:列表List和Set
    python数据类型:字符串
    python数据类型:Number数字
    Python控制语句
    Python运算符
    python基础语法
    Linux shell Script初识
    linux awk详解
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/13455474.html
Copyright © 2011-2022 走看看