zoukankan      html  css  js  c++  java
  • luogu P1731 生日蛋糕

    搬运工…………

    DFS

    蒟蒻搜索题学习+1

    题面传送门

    下面是思路:

    DFS状态:当前层 dep 这时的外表表面积 s ,这时的体积 v ,每一层的半径 r[] ,每一层的高度 h[]

    (普通的深搜肯定过不了,TLE)

    所以要剪枝

    1、r、h可以看出来会有取值范围

    	r、h不可能小于dep(那当然哪,这是最小了!)
    
    	r、h不可能比下一层(r[dep+1]-1、h[dep+1]-1)还大(题目要求)
    
    	又有圆柱体体积公式,(这一层体积的最大值为n-v不是?)
        
        所以
    
    for(r[dep] = min((int)sqrt(n - v) , r[dep + 1] - 1); r[dep] >= dep; r[dep]--)
    		for(h[dep] = min((int)(double)((n-v) / r[dep] / r[dep]), h[dep + 1] - 1); h[dep] >= dep; h[dep]--)
    

    (枚举范围剪枝)

    2、我们可以来自上往下来想一想无n,m要求下1~i层最小的v情况会如何,那肯定是

    	r:1,2,3,4,5,6,······,i
        
        h:1,2,3,4,5,6,······,i
        
        v = π * r * r *h
        
        **所以如果当层 v 加 1 ~ dep-1层的最小v 大于 n,就可以剪枝了**
    

    (可行性剪枝)

    3、另外想想,如果侧面积呢?
    **
    如果当前的表面积 加 1 ~ dep-1层的最小s 大于 自己之前搜到的答案,就可以剪枝了**

    (最优性剪枝)

    4、由3可以继续推,

    设已经做了i层蛋糕,则还需做m-i层, 
    
    Si’:为第i层蛋糕的侧面积,       
    FSi:余下的侧面积
    
    根据定义:
         V=π*R*R*H(在这里统一删掉π)
         则有:
          2Vi= 2R[i+1] * R[i+i] * H[i+1] + ...+ 2Rm * Rm * Hm
                          (每一层的体积之和)
             = R[i+1] *  S[i+1]’ + ...+ Rm * Sm’
             ≤ R[i+1] * (S[i+1]’+ ...+ Sm’)    放缩法
             = R[i+1]*FSi (剩余侧面积)
     所以:
                   FSi ≥ 2Vi / Ri+1 
    

    引用自Fellyhosn这篇博客(自己懒得打了)

    (最优性剪枝)

    综上,我们可写出代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,ans=0x3f3f3f3f;
    int min_s[1000],min_v[1000],r[1000],h[1000];
    
    template <typename T> inline void scan(T &x){
    	x=0;int f=1;char c=getchar();
    	while(c>'9'||c<'0'){if(c=='-')f=-f;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	x*=f;
    }
    
    void search(int dep,int s,int v){
    	if(dep==0){
    		if(v==n){
    			ans=min(s,ans);
    		}
    		return;
    	}
    	for(r[dep] = min((int)sqrt(n-v) , r[dep + 1] - 1) ; r[dep] >= dep ;r[dep]-- ){
    		for(h[dep] = min((int)(n-v) / r[dep] / r[dep] ,h[dep + 1] - 1) ;h[dep] >= dep ;h[dep]--){//1
    			if(v + min_v[dep-1] + r[dep] * r[dep] * h[dep]> n)continue;//2
    			if(s + min_s[dep - 1] + 2 * r[dep] * h[dep] >  ans)continue;//3
    			if(s + 2 * (n - v) / r[dep] > ans )continue;//4
    			if(dep == m)s += r[dep] * r[dep];
    			search(dep - 1,s + 2 * r[dep] * h[dep],v + r[dep] * r[dep] * h[dep]);
    			if(dep == m)s -= r[dep]*r[dep];//注意,加底面积得要放在这里,如果放在最后会超时!!!
    		}
    	}	
    	return;
    }
    int main(){
    	scan(n);scan(m);
    	for(int i=1;i<=m;i++){
    		min_s[i]=min_s[i-1]+2*i*i;
    		min_v[i]=min_v[i-1]+i*i*i;
    	}
    	r[m+1]=h[m+1]=0x3f3f3f3f;
    	search(m,0,0);
    	printf("%d
    ",ans%0x3f3f3f3f);
    	return 0;
    }
    
  • 相关阅读:
    Golang1.14.2 环境的安装
    Golang Module快速入门
    VS Code配置Go语言开发环境
    Go语言Mac、Linux、Windows 下交叉编译
    centerOS7 Yum 安装lnmp环境
    初步了解Fork/Join框架
    聊聊并发(七)——Java中的阻塞队列
    如何快速成长为技术大牛
    多线程-interrupt(),isInterrupted(),interrupted()(转)
    Rabbit MQ
  • 原文地址:https://www.cnblogs.com/fpjo/p/11405935.html
Copyright © 2011-2022 走看看