【NOI199九、LOJ#10019】生日蛋糕(搜索、最優化剪枝、可行性剪枝)

主要是剪枝的問題,見代碼,講的很詳細

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read(){
	char chr = getchar();	int f = 1,ans = 0;
	while(!isdigit(chr)) {if(chr == '-') f = -1;chr = getchar();}
	while(isdigit(chr))  {ans = (ans << 3) + (ans << 1);ans += chr - '0';chr = getchar();}
	return ans* f ;
}
void write(int x){
	if(x < 0) putchar('-'),x = -x;
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int r[50],h[50];//上一次的半徑、高
int N,M; 
int ans=0x3f3f3f3f;
void dfs(int x,int V,int S,int kk){//當前第x層,當前總共體積爲V,當前總側面積爲S,還有kk層沒有處理
	if(S+r[1]*r[1]+kk>=ans) return;//最優化剪枝,若是當前總側面積+底面積(三視圖角度理解)>=當前記錄的答案
	if(x>M+1) return;//超出M層
	if(N-V-r[x-1]*r[x-1]*h[x-1]*kk>0) return;//同上最優化剪枝,(假設以後每一層的底面積都是上一層的半徑與高)
	if(V==N && x==M+1){//若是能夠記錄進答案
		ans=min(ans,S+r[1]*r[1]);
		return;
	}
	for(int H=h[x-1]-1;H>=kk;H--)
	for(int R=r[x-1]-1;R>=kk;R--){//枚舉L,R,(上下界剪枝)
		h[x]=H;
		r[x]=R;
		V+=r[x]*r[x]*h[x];
		S+=2*r[x]*h[x];
		dfs(x+1,V,S,kk-1);
		V-=r[x]*r[x]*h[x];
		S-=2*r[x]*h[x];//回溯
	}
} 
int main(){
	N=read(),M=read();
	h[0]=(int)sqrt(N);
	r[0]=(int)sqrt(N);
	dfs(1,0,0,M);
	if(ans==0x3f3f3f3f)
		cout<<-1;//答案沒有更新過的話,輸出-1
	else
		cout<<ans;
	return 0;
}
相關文章
相關標籤/搜索