青蛙跳跃对调位置游戏的穷举解决算法
游戏在这里,让左边的青蛙和右边的青蛙对调位置。左边和右边各有三只青蛙,中心处有一个空位。每次可以跳一个青蛙,要么向前跳一格,要么跨过前方的青蛙跳一格,青蛙不能重叠,不能往回跳。
下面是解决该问题的穷举算法实现,算法已扩展到左边有任意只青蛙、右边有任意只青蛙、中间有任意个空位的情形:
lr4.h
1 #ifndef _LR4_H 2 #define _LR4_H 3 4 #ifdef __cplusplus 5 extern "C" { 6 #endif 7 8 int Resolve(int left, int blank, int right, int **ppMaps, int **ppMeds, int *pCount); 9 10 #ifdef __cplusplus 11 }; 12 #endif 13 14 #endif
lr4.c
1 #include <stdio.h> 2 #include <memory.h> 3 #include <malloc.h> 4 5 typedef int BOOL; 6 7 #define TRUE 1 8 #define FALSE 0 9 10 BOOL IsEqualMap(const int *pMap1, const int *pMap2, int total) 11 { 12 return memcmp(pMap1, pMap2, total * sizeof(int)) == 0; 13 } 14 15 void InitBeginTailMap(int left, int blank, int right, int *pBeginMap, int *pTailMap) 16 { 17 int index; 18 19 pTailMap += left + blank + right - 1; 20 21 for(index = 0; index < left; index += 1) 22 { 23 *pBeginMap++ = *pTailMap-- = -1; 24 } 25 26 for(index = 0; index < blank; index += 1) 27 { 28 *pBeginMap++ = *pTailMap-- = 0; 29 } 30 31 for(index = 0; index < right; index += 1) 32 { 33 *pBeginMap++ = *pTailMap-- = 1; 34 } 35 } 36 37 BOOL GetNextMap(const int *pCurrentMap, int *pNextMap, int med, int total) 38 { 39 if(pCurrentMap[med] != 0) 40 { 41 int med1 = med - pCurrentMap[med]; 42 int med2 = med1 - pCurrentMap[med]; 43 44 memcpy(pNextMap, pCurrentMap, total * sizeof(int)); 45 46 if(pNextMap[med] == 1) 47 { 48 if(med1 >= 0 && pNextMap[med1] == 0) 49 { 50 pNextMap[med1] = pNextMap[med]; 51 pNextMap[med] = 0; 52 53 return TRUE; 54 } 55 else if(med2 >= 0 && pNextMap[med2] == 0) 56 { 57 pNextMap[med2] = pNextMap[med]; 58 pNextMap[med] = 0; 59 60 return TRUE; 61 } 62 } 63 else 64 { 65 if(med1 < total && pNextMap[med1] == 0) 66 { 67 pNextMap[med1] = pNextMap[med]; 68 pNextMap[med] = 0; 69 70 return TRUE; 71 } 72 else if(med2 < total && pNextMap[med2] == 0) 73 { 74 pNextMap[med2] = pNextMap[med]; 75 pNextMap[med] = 0; 76 77 return TRUE; 78 } 79 } 80 } 81 82 return FALSE; 83 } 84 85 int Resolve(int left, int blank, int right, int **ppMaps, int **ppMeds, int *pCount) 86 { 87 BOOL result = FALSE; 88 int total = left + blank + right; 89 int *pEndMap = (int *)malloc(total * sizeof(int)); 90 int count = 0; 91 92 *ppMaps = NULL; 93 *ppMeds = NULL; 94 95 *ppMaps = (int *)realloc(*ppMaps, (count + 1) * total * sizeof(int)); 96 *ppMeds = (int *)realloc(*ppMeds, (count + 1) * sizeof(int)); 97 98 if(pEndMap == NULL || *ppMaps == NULL || *ppMeds == NULL) 99 { 100 return FALSE; 101 } 102 103 InitBeginTailMap(left, blank, right, ppMaps[0], pEndMap); 104 **ppMeds = -1; 105 count = 1; 106 107 while(TRUE) 108 { 109 if(count == 0) 110 { 111 break; 112 } 113 114 if(IsEqualMap(*ppMaps + (count - 1) * total, pEndMap, total)) 115 { 116 result = TRUE; 117 break; 118 } 119 120 (*ppMeds)[count - 1] += 1; 121 122 if((*ppMeds)[count - 1] >= total) 123 { 124 count -= 1; 125 } 126 else 127 { 128 *ppMaps = (int *)realloc(*ppMaps, (count + 1) * total * sizeof(int)); 129 *ppMeds = (int *)realloc(*ppMeds, (count + 1) * sizeof(int)); 130 131 if(*ppMaps == NULL || *ppMeds == NULL) 132 { 133 break; 134 } 135 136 if(GetNextMap(*ppMaps + (count - 1) * total, *ppMaps + count * total, (*ppMeds)[count - 1], total)) 137 { 138 (*ppMeds)[count] = -1; 139 140 count += 1; 141 } 142 } 143 } 144 145 if(!result) 146 { 147 if(*ppMaps != NULL) 148 { 149 free(*ppMaps); 150 } 151 152 if(*ppMeds != NULL) 153 { 154 free(*ppMeds); 155 } 156 } 157 158 *pCount = count; 159 160 return result; 161 }
main.c
1 #include <stdio.h> 2 #include "lr4.h" 3 4 int main() 5 { 6 int *pMaps, *pMeds, count; 7 int left = 4; 8 int blank = 2; 9 int right = 4; 10 11 if(Resolve(left, blank, right, &pMaps, &pMeds, &count)) 12 { 13 int total = left + blank + right; 14 int index, index2; 15 16 for(index = 0; index < count; index += 1) 17 { 18 if(index == 0) 19 { 20 printf("初始状态局面:"); 21 } 22 else 23 { 24 printf("第%2d步后局面:", index); 25 } 26 27 for(index2 = 0; index2 < total; index2 += 1) 28 { 29 printf("%3d", pMaps[index * total + index2]); 30 } 31 32 if(index != count - 1) 33 { 34 printf(" 跳左起第%d个青蛙\n", pMeds[index] + 1); 35 } 36 } 37 38 printf("\n"); 39 40 free(pMeds); 41 free(pMaps); 42 } 43 44 return 0; 45 }
示例输出:
左右各三只青蛙,中间一个空位的情形:
初始状态局面: -1 -1 -1 0 1 1 1 跳左起第3个青蛙
第 1步后局面: -1 -1 0 -1 1 1 1 跳左起第5个青蛙
第 2步后局面: -1 -1 1 -1 0 1 1 跳左起第6个青蛙
第 3步后局面: -1 -1 1 -1 1 0 1 跳左起第4个青蛙
第 4步后局面: -1 -1 1 0 1 -1 1 跳左起第2个青蛙
第 5步后局面: -1 0 1 -1 1 -1 1 跳左起第1个青蛙
第 6步后局面: 0 -1 1 -1 1 -1 1 跳左起第3个青蛙
第 7步后局面: 1 -1 0 -1 1 -1 1 跳左起第5个青蛙
第 8步后局面: 1 -1 1 -1 0 -1 1 跳左起第7个青蛙
第 9步后局面: 1 -1 1 -1 1 -1 0 跳左起第6个青蛙
第10步后局面: 1 -1 1 -1 1 0 -1 跳左起第4个青蛙
第11步后局面: 1 -1 1 0 1 -1 -1 跳左起第2个青蛙
第12步后局面: 1 0 1 -1 1 -1 -1 跳左起第3个青蛙
第13步后局面: 1 1 0 -1 1 -1 -1 跳左起第5个青蛙
第14步后局面: 1 1 1 -1 0 -1 -1 跳左起第4个青蛙
第15步后局面: 1 1 1 0 -1 -1 -1
左右各四个青蛙,中间两个空位的情形:
初始状态局面: -1 -1 -1 -1 0 0 1 1 1 1 跳左起第3个青蛙
第 1步后局面: -1 -1 0 -1 -1 0 1 1 1 1 跳左起第1个青蛙
第 2步后局面: 0 -1 -1 -1 -1 0 1 1 1 1 跳左起第5个青蛙
第 3步后局面: 0 -1 -1 -1 0 -1 1 1 1 1 跳左起第7个青蛙
第 4步后局面: 0 -1 -1 -1 1 -1 0 1 1 1 跳左起第8个青蛙
第 5步后局面: 0 -1 -1 -1 1 -1 1 0 1 1 跳左起第6个青蛙
第 6步后局面: 0 -1 -1 -1 1 0 1 -1 1 1 跳左起第4个青蛙
第 7步后局面: 0 -1 -1 0 1 -1 1 -1 1 1 跳左起第3个青蛙
第 8步后局面: 0 -1 0 -1 1 -1 1 -1 1 1 跳左起第5个青蛙
第 9步后局面: 0 -1 1 -1 0 -1 1 -1 1 1 跳左起第3个青蛙
第10步后局面: 1 -1 0 -1 0 -1 1 -1 1 1 跳左起第2个青蛙
第11步后局面: 1 0 -1 -1 0 -1 1 -1 1 1 跳左起第7个青蛙
第12步后局面: 1 0 -1 -1 1 -1 0 -1 1 1 跳左起第9个青蛙
第13步后局面: 1 0 -1 -1 1 -1 1 -1 0 1 跳左起第10个青蛙
第14步后局面: 1 0 -1 -1 1 -1 1 -1 1 0 跳左起第8个青蛙
第15步后局面: 1 0 -1 -1 1 -1 1 0 1 -1 跳左起第6个青蛙
第16步后局面: 1 0 -1 -1 1 0 1 -1 1 -1 跳左起第4个青蛙
第17步后局面: 1 0 -1 0 1 -1 1 -1 1 -1 跳左起第3个青蛙
第18步后局面: 1 0 0 -1 1 -1 1 -1 1 -1 跳左起第5个青蛙
第19步后局面: 1 0 1 -1 0 -1 1 -1 1 -1 跳左起第3个青蛙
第20步后局面: 1 1 0 -1 0 -1 1 -1 1 -1 跳左起第7个青蛙
第21步后局面: 1 1 0 -1 1 -1 0 -1 1 -1 跳左起第5个青蛙
第22步后局面: 1 1 1 -1 0 -1 0 -1 1 -1 跳左起第4个青蛙
第23步后局面: 1 1 1 0 -1 -1 0 -1 1 -1 跳左起第9个青蛙
第24步后局面: 1 1 1 0 -1 -1 1 -1 0 -1 跳左起第8个青蛙
第25步后局面: 1 1 1 0 -1 -1 1 0 -1 -1 跳左起第6个青蛙
第26步后局面: 1 1 1 0 -1 0 1 -1 -1 -1 跳左起第5个青蛙
第27步后局面: 1 1 1 0 0 -1 1 -1 -1 -1 跳左起第7个青蛙
第28步后局面: 1 1 1 0 1 -1 0 -1 -1 -1 跳左起第5个青蛙
第29步后局面: 1 1 1 1 0 -1 0 -1 -1 -1 跳左起第6个青蛙
第30步后局面: 1 1 1 1 0 0 -1 -1 -1 -1