生日蛋糕(noi99)

来源:互联网 发布:小米手机抹除数据 编辑:程序博客网 时间:2024/04/29 01:33
经过几天的研究。。。终于完成了生日蛋糕~(noi99)
剪枝非常明显~
注意:
2*(n-v)/r+s>=opt,不能写成2/r*(n-v)+s,之前犯了这个错误,就tle,估计还可能是死循环。。。
main函数里就不要用for循环了,用了也会tle.
3个重要的剪枝:
当已有体积加上剩余的最小体积大于总体积时剪枝;
当已有面积加上剩余最小体积大于当前最优面积时剪枝;
当2倍的剩余体积除以当前半径加上已有面积大于当前最优面积时剪枝(
2*(n-v)/r+s>=opt),证明,略;
  1. #include<iostream>
  2. using namespace std;
  3. const int oo = 1e10;
  4. int mins[21],minv[21],m,n,opt;
  5. void solve ( int v ,int s ,int level , int r , int h )
  6. {
  7.     int i,j,hh;
  8.     
  9.     if ( level==0 )
  10.     {
  11.         if ( v==n && s<opt )
  12.             opt=s;
  13.         return;
  14.     }
  15.     if (  v+minv[level-1]>n  || s+mins[level-1]>opt || 2*(n-v)/r+s>=opt )   
  16.         return ;
  17.     for ( i=r-1 ; i>=level ; i-- )
  18.     {
  19.         if ( level==m )
  20.                 s=i*i;
  21.         hh=min((n-v-minv[level-1])/(i*i),h-1);
  22.         for ( j=hh ; j>=level ; j-- )
  23.             solve(v+i*i*j,s+2*i*j,level-1,i,j);
  24.     }
  25. }
  26. int main ( )
  27. {
  28.     int i;
  29.     scanf("%d%d",&n,&m);
  30.     opt=oo;
  31.     for(i=1,minv[0]=mins[0]=0;i<21;i++)
  32.     {
  33.         mins[i]=mins[i-1]+2*i*i;
  34.         minv[i]=minv[i-1]+i*i*i;
  35.     }
  36.     solve(0,0,m,n+1,n+1);
  37.     if ( opt==oo )
  38.         printf("0/n");
  39.     else
  40.         printf("%d/n",opt);
  41. }


原创粉丝点击