#include<iostream>
#include<cmath>
using namespace std;
bool flag;
const int oo = 1e10;
int mins[21],minv[21],maxv[10001][21];
int m,n,opt,rr[1000],hh[1000],bestr[1000],besth[1000];
void solve ( int v ,int s ,int level , int r , int h )
{
int i,j,rmax,rmin,hmax,hmin;
if ( level==0 )
{
if ( v==n && s<opt )
opt=s;
return;
}
if ( v+minv[level]>n || s+mins[level]>opt || 2/r*(n-v)+s>=opt )
return ;
for ( i=r-1; i>=level ; i-- )
for ( j=h-1 ; j>=level ; j-- )
{
if ( v+i*i*j*level<n )
return ;
solve(v+i*i*j,s+2*i*j,level-1,i,j);
}
}
int main ( )
{
int i,j;
scanf("%d%d",&n,&m);
opt=oo;
for(i=1,minv[0]=mins[0]=0;i<21;i++)
{
mins[i]=mins[i-1]+2*i*i;
minv[i]=minv[i-1]+i*i*i;
}
memset(maxv,0,sizeof(maxv));
for ( i=1 ; i<10001 ; i++ )
for ( j=1 ; j<21 ; j++ )
maxv[i][j]=maxv[i-1][j-1]+i*i*j;
for ( i=m ; i<=n ; i++ )
for ( j=m ; j<=n ; j++ )
{
//rr[0]=i,hh[0]=j;
solve(i*i*j,i*i+2*i*j,m-1,i,j);
}
if ( opt==oo )
printf("0/n");
else
{
/*for ( i=0 ; i<m ; i++ )
printf("%d %d/n",bestr[i],besth[i]);*/
printf("%d/n",opt);
}
}
----------------------------------郁闷的分界线---------------------------------------------------------------
如何剪枝呢~我的程序跑的超慢。。。input 9876 6 output 1448 这组数据我本地跑了6秒。。。
我已经加了4个剪枝
v+minv[level]>n
当已有体积加上当前最小体积大于总体积时剪枝
s+mins[level]>opt
当已有面积加上当前最小面积大于已搜出的最优面积时剪枝
2/r*(n-v)+s>=opt
这是从lrj的书上看来的一个剪枝
v+i*i*j*level<n
当已有体积加上当前最大体积小于总体积时剪枝
哪里还能加剪枝呢?
#include<cmath>
using namespace std;
bool flag;
const int oo = 1e10;
int mins[21],minv[21],maxv[10001][21];
int m,n,opt,rr[1000],hh[1000],bestr[1000],besth[1000];
void solve ( int v ,int s ,int level , int r , int h )
{
int i,j,rmax,rmin,hmax,hmin;
if ( level==0 )
{
if ( v==n && s<opt )
opt=s;
return;
}
if ( v+minv[level]>n || s+mins[level]>opt || 2/r*(n-v)+s>=opt )
return ;
for ( i=r-1; i>=level ; i-- )
for ( j=h-1 ; j>=level ; j-- )
{
if ( v+i*i*j*level<n )
return ;
solve(v+i*i*j,s+2*i*j,level-1,i,j);
}
}
int main ( )
{
int i,j;
scanf("%d%d",&n,&m);
opt=oo;
for(i=1,minv[0]=mins[0]=0;i<21;i++)
{
mins[i]=mins[i-1]+2*i*i;
minv[i]=minv[i-1]+i*i*i;
}
memset(maxv,0,sizeof(maxv));
for ( i=1 ; i<10001 ; i++ )
for ( j=1 ; j<21 ; j++ )
maxv[i][j]=maxv[i-1][j-1]+i*i*j;
for ( i=m ; i<=n ; i++ )
for ( j=m ; j<=n ; j++ )
{
//rr[0]=i,hh[0]=j;
solve(i*i*j,i*i+2*i*j,m-1,i,j);
}
if ( opt==oo )
printf("0/n");
else
{
/*for ( i=0 ; i<m ; i++ )
printf("%d %d/n",bestr[i],besth[i]);*/
printf("%d/n",opt);
}
}
----------------------------------郁闷的分界线---------------------------------------------------------------
如何剪枝呢~我的程序跑的超慢。。。input 9876 6 output 1448 这组数据我本地跑了6秒。。。
我已经加了4个剪枝
v+minv[level]>n
当已有体积加上当前最小体积大于总体积时剪枝
s+mins[level]>opt
当已有面积加上当前最小面积大于已搜出的最优面积时剪枝
2/r*(n-v)+s>=opt
这是从lrj的书上看来的一个剪枝
v+i*i*j*level<n
当已有体积加上当前最大体积小于总体积时剪枝
哪里还能加剪枝呢?