原址:http://blog.csdn.net/gogdizzy/article/details/6563626
假设由A到B需要k步,分别是A1,A2,……Ak,每一步都是(5,-5,7,-7,12,-12)中一个。因为最终结果就是
A1+A2+……+Ak,所以这k步是可以调换顺序的(加法交换律)。
1> 如果这k步里,同时存在5,-5,那么可以约去。同理,(7,-7),(12,-12)也是。即最多存在8种选择,选定了一个数,那么它的相反数就不能出现。
2> 7+5=12,(-7)+(-5)=(-12),12+(-7)=5,12+(-5)=7,(-12)+7=(-5),(-12)+5=(-7),
即(7,5)(-7,-5)(12,-7)(12,-5)(-12,7)(-12,5)任何一对都不能同时出现,这样,又进一步缩小了范围。
可能性只有
5 -7的组合
-5 7的组合
5 12的组合
7 12的组合
-5 -12的组合
-7 -12的组合
3> 如果有7个5,可以用5个7替代,所以知道5的个数不超过7,同理,有
-5的个数不超过7
7的个数不超过12
-7的个数不超过12
有了这么多限制条件,只需要试一下即可。
- /**
- * 用5,7,12加减运算,最少步骤到大n
- * gogdizzy@gmail.com
- */
- #include <stdio.h>
- #define abs(x) /
- ( (x^(x>>31))-(x>>31) )
- int min_step( int N )
- {
- int diff;
- int n5, n7, n12;
- int r5, r7, r12;
- unsigned tmp, total = unsigned (-1); // assign a very big num
- for( n5 = -6; n5 < 7; ++n5 )
- {
- diff = N - 5 * n5;
- n7 = diff / 7;
- n12 = diff / 12;
- if( 12 * n12 + 5 * n5 == N )
- {
- tmp = abs( n5 ) + abs( n12 );
- if( total > tmp ) r5 = n5, r7 = 0, r12 = n12, total = tmp;
- }
- else if( 7 * n7 + 5 * n5 == N )
- {
- if( n7 > -12 && n7 < 12 )
- {
- tmp = abs( n5 ) + abs( n7 );
- if( total > tmp ) r5 = n5, r7 = n7, r12 = 0, total = tmp;
- }
- }
- }
- for( n7 = -11; n7 < 12; ++n7 )
- {
- n12 = ( N - 7 * n7 ) / 12;
- if( 7 * n7 + 12 * n12 == N )
- {
- tmp = abs( n7 ) + abs( n12 );
- if( total > tmp ) r5 = 0, r7 = n7, r12 = n12, total = tmp;
- }
- }
- printf( "%d = (%d) * 5 + (%d) * 7 + (%d) * 12/ntotal:%d/n", N, r5, r7, r12, total );
- return total;
- }
- int main()
- {
- int n;
- scanf( "%d", &n );
- min_step( n );
- return 0;
- }