深搜前面已经讲过,对于剪枝,就是把没必要的步骤进行if特判剪枝,用好了可以大大的优化复杂度
这里就根据两个例题来讲吧
1440:【例题1】数的划分
详情见代码
#include<cstdio> #include<cstring> #include<algorithm> int n,k; int f[210][7]; int main() { scanf("%d%d",&n,&k); memset(f,0,sizeof(f)); //f数组先初始化为0, f[0][0]=1;//但是第一个要为1,为了防止加来加去都是0 for(int i=1;i<=n;i++)//总和的循环 for(int j=i;j<=n;j++)//也是总和的循环,因为前面已经循环了i,所以j可以直接由i开始 //循环两次是为了后面状态的处理做铺垫 for(int x=1;x<=k;x++)//这是循环方案数 { f[j][x]=f[j][x]+f[j-i][x-1];//f[j][x]就是方案总数的最大值 //j-i是为了防止重复,比如说:1 1 5,1 5 1,5 1 1 这样的情况出现 //x-1就是上一个的最大值,是为了继承的 } printf("%d\n",f[n][k]);//输出最大值 return 0; }
1441:【例题2】生日蛋糕
详情见代码
include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; const int maxn=0x3f3f3f3f; const int minn=-0x3f3f3f3f; int n,m,ans,a[10086],b[10086]; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } /* 体积V=πR2H 侧面积A=2πRH 底面积A=πR2 */ void dfs(int v/*已用体积*/,int s/*表面积*/,int p/*剩余层数 注意是剩余*/,int r/*半径*/,int h/*高*/) { if(p==0) { //如果已经搜没有剩余的层数了那就不用搜了! if (v==n&&s<ans) ans=s; return ; } if(v+b[p-1]>n) return ;//如果已用体积加上这层的最大体积大于了n那还搜个屁! if(s+a[p-1]>ans) return ; if(2*(n-v)/r+s>=ans) return; //当前的表面积+余下的侧面积>当前最优值那还搜个屁! for(int i=r-1; i>=p; i--) { //半径 if(p==m) s=i*i; int pyyyyyy=min((n-v-b[p-1])/(i*i),h-1); for(int j=pyyyyyy; j>=p; j--) //高 dfs(v+i*i*j,s+2*i*j,p-1,i,j); } } int main() { n=read(); m=read(); cin>>n>>m; ans=maxn; a[0]=0; b[0]=0; for(int i=1; i<21; i++) { a[i]=a[i-1]+2*i*i;//i层的最大表面积 b[i]=b[i-1]+i*i*i;//i层的最大体积 体积V=πR2H } dfs(0,0,m,n+1,n+1);//进行搜索 //5个量的意思看上 if(ans==maxn) cout<<0; else cout<<ans; return 0; }