《算法竞赛进阶指南》0x23剪枝 POJ1190上下界搜索与剪枝

题目链接:http://poj.org/problem?id=1190

剪枝的常用思考策略:优化搜索顺序(从决策数量越少的位置开始决策)、排除冗余的等效的操作、可行性剪枝、最优性剪枝、上下界剪枝,其中在可行性剪枝方面可以利用“未来期望进行剪枝”

要充分利用不等式关系进行放缩,将不可能的状态进行剪枝,也是一个对“未来状态的估计”。

代码:

#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std;
#define maxn 25
const int inf=0x3f3f3f3f;
int n,m;
int minv[maxn],mins[maxn];
int h[maxn],r[maxn];
int ans=inf;
void dfs(int dep,int s,int v){
    
    if(mins[dep]+s >= ans)return ;
    if(minv[dep]+v > n)return ;
    if(2*(n-v)/r[dep+1]+s >= ans) return ;
    
    if(dep==0){
        if(n==v)ans=min(ans,s);
        return ;
    }
    //枚举上下界 
    for(int R=min((int)sqrt((double)n-v),r[dep+1]-1);R>=dep;R--)
        for(int H=min((n-v)/R/R,h[dep+1]-1);H>=dep;H--){            
            int t=0;
            if(dep==m)t=R*R;//所有的上表面都加到最后一层上
            r[dep]=R;
            h[dep]=H;
            dfs(dep-1,s+2*R*H+t,v+R*R*H);
        }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){//计算前i层的最小面积和体积 
        mins[i]=mins[i-1]+2*i*i;
        minv[i]=minv[i-1]+i*i*i; 
    }
    r[m+1]=h[m+1]=inf;//保证最后一行的时候上界无限制 
    dfs(m,0,0);
    if(ans==inf)cout<<0<<endl;
    else cout<<ans<<endl;    
}

猜你喜欢

转载自www.cnblogs.com/randy-lo/p/13163123.html
今日推荐