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;
    }
  • 相关阅读:
    svn cleanup failed–previous operation has not finished 解决方法
    开源SNS社区系统推荐
    从网络获取图片本地保存
    MS SQL Server 数据库连接字符串
    KeepAlive
    Configure Git in debian
    sqlserver query time
    RPi Text to Speech (Speech Synthesis)
    SQL Joins with C# LINQ
    search or reseed identity columns in sqlserver 2008
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/13455474.html
Copyright © 2011-2022 走看看