- 论坛徽章:
- 0
|
老大们,请教算法问题,很难
[quote]原帖由 "chenjn"]我觉得只要在A1-An任何一个地方和相邻的牌不出现一次以上的移动,应该就是最少的了[/quote 发表:
我觉得这道题,仔细分析一下,就比较简单了,而且感觉题目出的不够灵活,chenjin 的算法应该没有问题。
思路大致如下:
首先得满足其中一个边界,如 cards [0], 只能通过和右边的 cards [1] 交换牌数来实现,得到满足后,就不必理会 cards [0]了,边界自然就变成了cards [1], 问题的范围缩小,依此类推,很显然用递归算法是很容易实现的。
下面是自己编着玩的另外一种类似方法,同样是递归实现,刚开始学编程,多包含:
- /* 采用递归算法 */
- #include <stdlib.h>;
- #define HEAP 6 /* 堆数,自行修改 */
- #define AVERAGE 10 /* 平均每堆牌数 */
-
- int move( int [], int);
-
- int main()
- {
- int cards [ HEAP ] = { 8, 9, 13, 6, 9, 15 };
-
- int i;
- printf ( "Before move:\n");
- for ( i = 0; i <= HEAP -1; i++)
- printf ( "%d ", cards [i] );
-
- printf ("\nMoving...\n");
-
- printf ( "Move steps: %d\nAfter Move:\n\
- ", move ( cards, HEAP ));
-
- for ( i = 0; i <= HEAP -1; i++)
- printf ( "%d ", cards[i]);
- printf ("\n");
- }
-
- int move ( int c [], int size) /* 模拟传引用, 递数组和大小 */
- {
- static count = 0; /* 统计步数 */
-
- if ( size == 1 )
- return count;
-
- else {
- int n;
- n = size/2; /* 把数组拆成两块,取前 n 堆牌 */
-
- int i;
- int foresum = 0;
- for ( i = 0; i <= n-1; i++) /* 计算前 n 堆牌总数 */
- foresum += c[i];
-
-
- if ( foresum >; n * AVERAGE ) {
- c[n-1] -= foresum - n * AVERAGE;
- c[n] += foresum - n * AVERAGE;
- count += 1;
- }
-
- else if ( foresum < n * AVERAGE ) {
- c[n-1] += n * AVERAGE - foresum;
- c[n] -= n * AVERAGE - foresum;
- count += 1;
- }
-
- for ( i = 0; i <= HEAP -1; i++)
- /* 打印每次移动后结果, 这里感觉有问题,请指点 */
- printf ( "%d ", c[i]);
- printf ("\n");
-
- move ( c, n ); /* 递归开始 */
- move ( &c[n], size - n );
- }
-
- }
复制代码 |
|