- 注册时间
- 2008-8-4
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 1415
- 在线时间
- 小时
|
发表于 2008-9-13 18:16:38
|
显示全部楼层
- #include < iostream.h >
- #include < math.h >
-
- #include "D:/HugeCalc/HugeCalc.h" // 公共接口
- #include "D:/HugeCalc/HugeInt.h" // 10进制系统
- #include "D:/HugeCalc/HugeIntX.h" // 16进制系统
-
- #pragma message( "automatic link to D:/HugeCalc/HugeCalc.lib" )
- #pragma comment( lib, "D:/HugeCalc/HugeCalc.lib" )
-
- const unsigned __int16 Pri1024 = 172; // 1024 以内的素数个数
- const unsigned __int16 Pri2048 = 309; // 2048 以内的素数个数
-
- const __int64 BOUND32 = (1ul << 32) - 1;
- const __int64 BOUND14 = (1ul << 14) - 1;
- const __int64 BOUND10 = (1ul << 10) - 1;
-
- typedef CHugeIntX integer;
-
- unsigned __int16 arr[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039 };
-
- //const unsigned __int32 ProblemSize = 1023;
- //unsigned __int16 arr[ProblemSize];
-
- __int32 MinimumGroup(const unsigned __int16* const arr, const unsigned __int16 _SIZE, const __int64 _BOUND);
-
- int main(/*int argc, char* argv[]*/ void)
- {
- __int32 result;
-
- //for ( __int16 i=0; i<ProblemSize; i++) arr[ i ] = i + 2;
- cout << "Call " << HugeCalc::GetVer() << endl;
-
- HugeCalc::EnableTimer();
- HugeCalc::ResetTimer(0, TIMER_UNIT_ms);
-
- //result = MinimumGroup(arr, ProblemSize, BOUND32);
- //result = MinimumGroup(arr, 25, BOUND14); // 贪婪法=10,最优=9
- //result = MinimumGroup(arr, 36, 22500ul); // 贪婪法=15,最优=14
- //result = MinimumGroup(arr, 72, 8100ul); // 贪婪法=最优=49
- //result = MinimumGroup(arr, Pri1024, BOUND10); // 贪婪法=最优=162
- //result = MinimumGroup(arr, Pri1024, BOUND10*29); // 贪婪法=最优=133
- result = MinimumGroup(arr, Pri1024, BOUND32);
- //result = MinimumGroup(arr, Pri2048, BOUND32);
-
- HugeCalc::EnableTimer( FALSE );
-
- cout << endl << "Best result = " << result << endl;
-
- cout << endl << HugeCalc::GetTimerStr() << endl;
-
- system( "pause" );
-
- return 0;
- }
-
- // 函数名: MinimumGroup
- // 函数功能: 求出把一组正整数 arr[0] ~ arr[_SIZE-1] 划分成最少的组数的方法,使得每组里所有数之积均不大于 _BOUND
- //
- // 输入参数:
- // arr: unsigned __int16,数组指针,要求 arr[] 是升序排列
- // _SIZE: unsigned __int16,数组的大小
- // _BOUND: __int64,分组的乘积最大值
- //
- // 输出参数: __int32,最小分组数
- // 结果为 0: _SIZE = 0
- // 结果为 -1: _BOUND < arr[_SIZE-1]
- // 结果为 -2: arr 不是升序排列
- //
- // 版本 : 1.2.5.9
- // 修改时间: 2008-9-11 00:30
- //
- // 存在问题: 运算效率很低,限界条件不够精细
- // 下一版本改进措施; 乘法变加法,把 arr[]、_BOUND 都取对数,然后扩大某个倍数,化成整数加减运算
-
- __int32 MinimumGroup(const unsigned __int16* const arr, const unsigned __int16 _SIZE, const __int64 _BOUND)
- {
- __int32 i, j, k, icur, g, gMin, gMax, gCur, top, bottom, top0, bottom1, top1, Lpro, numOfBig, Lpromin;
- __int32 *bUsed, *pbuf;
-
- __int64 product, maxV, minGV, *pmaxV, *pminGV, *ppro;
-
- top0 = _SIZE - 1;
-
- if ( 0 == _SIZE ) return (0);
- if ( _BOUND < arr[top0] ) return (-1);
-
- for ( i=0; i<top0; ++i )
- {
- if ( arr[i] > arr[i+1] )
- return (-2);
- }
-
- if ( 0 == arr[0] || 1 == arr[top0] ) return (1);
-
- for ( i=0 ; 1 == arr[i] ; ++i ); // 1不参加运算
-
- if ( i == top0 ) return (1);
-
- bottom1 = i;
-
- for (maxV=_BOUND/arr[bottom1], i=top0 ; i>bottom1 && arr[i]>maxV ; --i ); // 只能单独做一组的数
-
- if ( i - bottom1 < 2 ) return (_SIZE - i);
-
- top1 = i;
-
- integer hollpro(arr[bottom1]), grpV(_BOUND), b(_BOUND);
-
- for ( j=1, i=1+bottom1 ; i<=top1 ; ++i )
- {
- hollpro *= arr[i];
- if ( hollpro > grpV )
- {
- grpV *= b;
- ++j;
- }
- }
- grpV = 0;
-
- numOfBig = top0 - top1;
- gMin = j + numOfBig;
- if ( j == 1 ) return (gMin);
-
- // 用贪婪法求分组数的一个上界 gMax,此方法来自 gxqcn
- bUsed = new __int32 [_SIZE];
-
- for ( i=0; i<_SIZE; ++i ) bUsed[i] = 0;
-
- cout << endl;
-
- for ( gMax=0, bottom=0, top=top0 ; bottom != top ; )
- {
- ++gMax;
- cout << "No. " << gMax << " : ";
-
- //for ( product=1, maxV=_BOUND, i=top ; i >= bottom; --i )
- for ( maxV=_BOUND, i=top ; i >= bottom; --i )
- {
- if ( !bUsed[i] && arr[i] <= maxV )
- {
- cout << " " << arr[i];
- //maxV = _BOUND / ( product *= arr[i] );
- maxV /= arr[i];
- bUsed[i] = 1;
- }
- }
- //cout << " " << product;
- cout << endl;
-
- while ( bottom != top && bUsed[top] ) --top;
- while ( bottom != top && bUsed[bottom] ) ++bottom;
- }
- if ( !bUsed[top] )
- {
- ++gMax;
- //cout << "No. " << gMax << " : " << arr[top] << " " << arr[top] << endl;
- cout << "No. " << gMax << " : " << arr[top] << endl;
- }
-
- if ( gMax == gMin )
- {
- delete [] bUsed;
- return (gMax); // 上界 = 下界
- }
-
- // 尝试组数更小的方案
-
- // 求第一组的数字的个数
- for ( Lpromin=0, maxV=_BOUND, i=top1 ; i >= bottom1; --i )
- {
- if ( arr[i] <= maxV )
- {
- maxV /= arr[i];
- ++Lpromin;
- }
- }
-
- k = gMax - numOfBig;
-
- for ( maxV=_BOUND, i=bottom1; arr[i]<=maxV; ++i ) maxV /= arr[i] ;
-
- Lpro = i - bottom1 + 1; // 最长乘式的因子数+1
- j = Lpro * gMax;
- pbuf = new __int32 [j]; // 所有分组因子下标表格
- pmaxV = new __int64 [j]; // 同组的下一个乘积因子允许的最大值
- ppro = new __int64 [j]; // 本组前几个因子的乘积
- pminGV = new __int64 [gMax]; // 每一组乘积允许的最小值
-
- integer *pGV, *pB, q, r, c;
-
- pGV = new integer [gMax]; // 本组之后未分配的数的乘积
- pB = new integer [k]; // 界限参数(_BOUND的乘幂)
-
- for ( i=0; i<j; ++i ) pbuf[i] = 0;
- for ( i=0; i<j; ++i ) pmaxV[i] = 0;
- for ( i=0; i<j; ++i ) ppro[i] = 0;
-
- for ( top=top0, i=1; i<=numOfBig ; ++i, --top )
- {
- pbuf[i * Lpro ] = 1;
- pbuf[i * Lpro + 1] = top;
-
- ppro[i * Lpro ] = 1;
- ppro[i * Lpro + 1] = arr[top];
-
- bUsed[top] = 1;
- }
-
- icur = Lpro-2+bottom1;
- if ( Lpromin <= 2 )
- {
- for ( i=icur; i<top1; ++i ) pmaxV[i] = _BOUND - ( _BOUND % arr[i] );
- }
- else
- {
- for ( i=icur; i<top1; ++i )
- {
- maxV = _BOUND / arr[i];
- g = __int32(maxV % arr[bottom1]);
- for ( j=bottom1+1; g>0 && j<i; ++j)
- {
- gCur = __int32(maxV % arr[j]);
- if ( g > gCur )
- g = gCur;
- }
- pmaxV[i] = ( maxV - g ) * arr[i];
- }
- }
-
- // 选择排序
- for ( i=icur; i<icur+k-1; ++i )
- {
- for ( g=i, maxV=pmaxV[i], j=i+1; j<top1; ++j )
- {
- if ( maxV < pmaxV[j] )
- {
- maxV = pmaxV[j];
- g = j;
- }
- }
- if ( g != i )
- {
- pmaxV[g] = pmaxV[i];
- pmaxV[i]= maxV;
- }
- }
-
- for ( pB[0]=1, pB[1]=pmaxV[icur], j=icur, i=2; i<k; ++i )
- {
- ++j;
- pB[i] = pB[i-1] * ( q = pmaxV[j] );
- }
- //for ( pB[0]=1, pB[1]=b, i=2; i<k; ++i ) pB[i] = pB[i-1] * b;
- b = 0;
-
- for ( i=numOfBig+1; i<gMax; ++i ) pmaxV[i * Lpro] = _BOUND;
-
- pGV[numOfBig] = hollpro;
-
- for ( gCur=gMax-1 ; gCur >= gMin ; --gCur ) // 组数循环
- {
- for ( top=top1, i=bottom=bottom1; i<=top; ++i ) bUsed[i] = 0;
-
- for ( g=numOfBig+1 ; g<gCur ; ) // g 循环
- {
- q.Div( pGV[g-1], pB[gCur-g], &r );
- if ( !(!r) ) ++q;
- pminGV[g] = minGV = q;
-
- k = 1;
- pbuf[g*Lpro+k] = top;
- ppro[g*Lpro+k] = product = arr[top];
- pmaxV[g*Lpro+k] = maxV = _BOUND / product;
- bUsed[top] = 1;
- icur = --top;
-
- // 生成第 g 组乘积
- do {
- for ( i=icur; i>=bottom; --i )
- {
- if ( !bUsed[i] && arr[i] <= maxV )
- {
- ++k;
- pbuf[g*Lpro+k] = i;
- ppro[g*Lpro+k] = product *= arr[i];
- pmaxV[g*Lpro+k] = maxV /= arr[i] ;
- bUsed[i] = 1;
- }
- }
-
- if ( product >= minGV ) // 进入下一组
- {
- pbuf[g*Lpro] = k;
- pGV[g] = pGV[g-1] / (c = product);
-
- while ( bottom != top && bUsed[top] ) --top;
- while ( bottom != top && bUsed[bottom] ) ++bottom;
-
- ++g;
- break;
- }
-
- // 生成下一个乘积
- do {
- j = bottom;
-
- do {
- i = pbuf[g*Lpro+k];
- bUsed[i] = 0;
- --k;
-
- if ( i > top )
- {
- top = i;
- }
- else if ( i < bottom )
- {
- bottom = i;
- }
- } while ( k >= 1 && i < j );
-
- if ( k >= 1 )
- {
- icur = --i;
- maxV = pmaxV[g*Lpro+k];
- product = ppro[g*Lpro+k];
- break;
- }
-
- --g; // 退回到上一组
-
- if ( numOfBig == g ) // 退到底了
- {
- delete [] pB;
- delete [] pGV;
- delete [] pminGV;
- delete [] ppro;
- delete [] pmaxV;
- delete [] pbuf;
- delete [] bUsed;
-
- return (gCur+1);
- }
-
- k = pbuf[g*Lpro];
- minGV = pminGV[g];
-
- } while ( 1 ); // end of 生成下一个乘积
-
- } while ( 1 ); // end of 生成第 g 组乘积
-
- } // end of g 循环
-
- for ( j=0, i=top; i>=bottom; --i) // 最后一组
- {
- if ( !bUsed[i] )
- {
- ++j;
- pbuf[g*Lpro+j] = i;
- }
- }
- pbuf[g*Lpro] = j;
-
- // 输出
- cout << endl << "groups = " << gCur << endl;
- for ( i=1 ; i <= gCur ; ++i )
- {
- cout << "No. " << i << " : ";
-
- for ( k=pbuf[i*Lpro], j=1 ; j <= k ; ++j )
- cout << " " << arr[ pbuf[i * Lpro + j] ];
-
- cout << endl;
- }
- cout << endl;
-
- } // end of 组数循环
-
- delete [] pB;
- delete [] pGV;
- delete [] pminGV;
- delete [] ppro;
- delete [] pmaxV;
- delete [] pbuf;
- delete [] bUsed;
-
- return (gMin);
- }
复制代码 |
|