解题思路: 每次取最大木棍和最小木棍比较,若相等,则所有木棍长度相等,完成;否则将最大木棍一分为二,更新最小木棍。重复直至完成。
木棍实现:用结构体保存木棍一分为二的两种可能(L为奇数时),每次取木棍时尽量取其中奇数木棍(奇数和偶数相差1,奇数一分为二后有的两种长度包含了偶数一分为二后的长度)。
#include<cstdio>
#include<queue>
using namespace std;
const int INF = 1e9+1;
struct stick
{/*结构体保存每个木棍的可能*/
int l , r;
/*运算符重载*/
bool operator <(const stick &s)const
{
if( l==s.l )
{
return r<s.r;
}
return l<s.l;
}
bool operator ==(const stick &s)const
{
return ( (l==s.l) || (l==s.r) || (r==s.l) || (r==s.r) );
}
};
int main()
{
int n,L;
stick s,min_s;//min_s保存最小木棍
priority_queue<stick> que; //默认为大顶堆 每次取出最大木棍
min_s.l = min_s.r = INF;
scanf("%d",&n);
for( int i=0; i<n; i++ )
{
scanf("%d",&L);
s.l = s.r = L;
if( s<min_s ) min_s = s;
que.push(s);
}
int res = 0;
while( true )
{
s = que.top(); que.pop(); //每次取出最大木棍
if( min_s==s )
break; //所有木棍都一样长 退出
if( s.l&1 ) L = s.l;//(奇,偶);(奇,奇);(偶,奇);(偶,偶)
else L = s.r;//(偶,偶)时相同,所以只在l为奇时取
/*最大木棍一分为二后的长度*/
if( L&1 )
{
s.l = L/2;
s.r = L/2+1;
}
else
{
s.l = s.r = L/2;
}
if( s<min_s ) min_s = s;//更新最小木棍
que.push(s);
res++;
}
printf("%d\n",res);
return 0;
} 
京公网安备 11010502036488号