| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
N次tle后,终于AC了,16ms,几个重要截枝#include <stdio.h>
#include <algorithm>
void POJ1011();
int inputnum;
bool used[64];
int partlen[64];
int main()
{
POJ1011();
return 0;
}
//needstick为还需要拼凑的stick数,pos为目前所在part的偏移,
//leftlen为还剩下的棍子长度,sticklen为当前所需棍子的总长度,
//start为每个棍子的part起点
bool searchStick(int needstick,int pos,int leftlen,int sticklen,int start)
{
//找到一根
if(leftlen==0)
{
//如果是最后所需要的一根,则已找完所有棍子
if(needstick==1)
return true;
start=0;
while(used[start])
{
start++;
}
//找下一根
if(searchStick(needstick-1,start,sticklen,sticklen,start))
return true;
return false;
}
else
{
//如果棍子的part全部用光则表示失败
if(pos>inputnum-1)
return false;
int i;
//寻找当前part以及其后的所有part来拼凑一根棍子
for(i=pos;i<inputnum;++i)
{
//判断part是否用过,重要剪枝1
if(used[i])
continue;
//当前part大于剩下所需的长度,重要剪枝2
if(partlen[i]>leftlen)
continue;
//如果前面一个相等长度的棍子没有用上,那么这个也用不上,重要剪枝3
if(partlen[i]==partlen[i-1]&&!used[i-1])
continue;
used[i] = true;
if(searchStick(needstick,i+1,leftlen-partlen[i],sticklen,start))
return true;
used[i] = false;
//此剪枝未加导致以前的几次TLE,加上下面的剪枝就AC了
if(partlen[i]==leftlen)
return false;
if(i==start)
return false;
}
return false;
}
}
bool cmp(int a,int b)
{
return a>b;
}
void POJ1011()
{
int i;
scanf("%d",&inputnum);
while(inputnum!=0)
{
int maxnum,len,totallen=0,maxpart=0;
memset(used,0,sizeof(used));
for(i=0;i<inputnum;i++)
{
scanf("%d",partlen+i);
totallen+=partlen[i];
}
//descending sort
std::sort(partlen,partlen+inputnum,cmp);
maxnum = 64>totallen/partlen[0]?totallen/partlen[0]:64;
int num;
for(num = maxnum;num>0;--num)
{
if(totallen%num==0)
{
len = totallen/num;
if(searchStick(num,0,len,len,0))
{
printf("%d\n",len);
break;
}
}
}
scanf("%d",&inputnum);
}
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator