8跳棋(1)90跳棋(2)240跳棋(3)
跳棋(1)非常简单,我是自己随便搞搞就过了。
跳棋(2)把70改成了54,我就开始编程了。
代码:
#include<iostream> using namespace std; int number = 54; //number是剩余次数 //flag是上一次的运动方向,有8种:0开始,1上移,2下移,3上跳,4下跳,5左移,6右移,7左跳,8右跳 bool move(int list[][5],int mi,int mj,int flag) //(i,j)是空格 { int save_number = number; if (number <= 0)//判断是不是已经成功了 { for (int i = 0; i < 5; i++)for (int j = 0; j < 5; j++) if ((i<2 || j<2) && (list[i][j] == 1 || list[i][j] == 0))return false; else if ((i>2 || j>2 ) && list[i][j] %2 == 0)return false; return true; } number--; int ii, jj; //要移动的格子相对于空格的位移 for (int f = 1; f <= 8; f++) //8种flag { //防止无意义的死循环 if (flag + f == 3)continue; //1、2 else if (flag == 3 && f == 4)continue; //3、4 else if (flag == 4 && f == 3)continue; else if (flag * f == 30)continue; //5、6 else if (flag + f == 15)continue; //7、8 if (f <= 4) //确定ii和jj { jj = 0; if (f == 1)ii = 1; else if (f == 2)ii = -1; else if (f == 3)ii = 2; else ii = -2; } else { ii = 0; if (f == 5)jj = 1; else if (f == 6)jj = -1; else if (f == 7)jj = 2; else jj = -2; } if (mi + ii >= 0 && mi + ii < 5 && mj + jj >= 0 && mj + jj < 5 ) { if (list[mi + ii][mj + jj] == 1 && f % 2 == 0 || list[mi + ii][mj + jj] == 2 && f % 2 != 0)///这一步对于减少工作量至关重要 { list[mi][mj] = list[mi + ii][mj + jj]; //移动或者跳动 list[mi + ii][mj + jj] = 0; bool b = move(list, mi + ii, mj + jj, f); list[mi + ii][mj + jj] = list[mi][mj]; list[mi][mj] = 0; if (b) { cout << endl<<endl; if (f == 1)cout << "往上移动"; if (f == 2)cout << "往下移动"; if (f == 3)cout << "往上跳"; if (f == 4)cout << "往下跳"; if (f == 5)cout << "往左移动"; if (f == 6)cout << "往右移动"; if (f == 7)cout << "往左跳"; if (f == 8)cout << "往右跳"; for (int i = 0; i < 5; i++) { cout << endl; for (int j = 0; j < 5; j++) { if (list[i][j] == 1)cout << "○"; else if (list[i][j] == 2)cout << "●"; else cout << " "; } } return true; } } } } number = save_number; return false; } int main() { int list[5][5]; //list用来表示状态,0表示空格,1表示白子,2表示黑子,-1表示无效的8个格子 for (int i = 0; i < 5; i++) //初始化list { for (int j = 0; j < 5; j++) { if (i<3 && j<3)list[i][j] = 1; else if (i>1 && j>1)list[i][j] = 2; else list[i][j] = -1; } } list[2][2] = 0; move(list,2,2,0); cout << endl << endl << "注意,输出的顺序是反着的"; system("pause>nul"); return 0; }
其中,
if (list[mi + ii][mj + jj] == 1 && f % 2 == 0 || list[mi + ii][mj + jj] == 2 && f % 2 != 0)
这句话是使得黑子只能往上或者往左移动,白子只能往下或者往右移动。
这样做一定可以减掉大量的枝,节省大量时间,但是能不能找到需要的解反而不清楚,要看运行结果才知道。
事实证明,用这个剪枝之后可以得到最优解,而且很快就得到了。
运行结果:
跳棋(3)又把54改成了46
只需要修改全局变量 int number = 46; 即可
运行时间:大约40秒。
运行结果:
往左移动
●●●
●●●
● ●○○
○○○
○○○
往右跳
●●●
●●●
●○● ○
○○○
○○○
往右移动
●●●
●●●
●○●○
○○○
○○○
往左跳
●●●
●●●
●○ ○●
○○○
○○○
往上移动
●●●
●●
●○●○●
○○○
○○○
往下跳
●●●
●●○
●○●○●
○○
○○○
往下移动
●●●
●●○
●○●○●
○○○
○○
往上跳
●●●
●●○
●○ ○●
○○○
●○○
往左跳
●●●
●●○
○●○●
○○○
●○○
往上移动
●●●
●○
●○●○●
○○○
●○○
往右跳
●●●
○●
●○●○●
○○○
●○○
往下跳
●●●
○●○
●○●○●
○○
●○○
往上移动
●●●
○●○
●○ ○●
●○○
●○○
往左跳
●●●
○●○
○●○●
●○○
●○○
往右移动
●●●
○●○
○ ●○●
●○○
●○○
往右跳
●●●
○●○
○○● ●
●○○
●○○
往下跳
●●●
○●○
○○●○●
●○○
● ○
往左移动
●●●
○●○
○○●○●
●○○
●○
往右跳
●●●
○●○
○○●○●
●○○
○●
往上跳
●●●
○●○
○○●○
●○○
○●●
往左跳
●●●
○●○
○○ ○●
●○○
○●●
往上跳
●●
○●○
○○●○●
●○○
○●●
往左移动
● ●
○●○
○○●○●
●○○
○●●
往下跳
●○●
○●○
○ ●○●
●○○
○●●
往右跳
●○●
○●○
○○● ●
●○○
○●●
往下移动
●○●
○●○
○○●○●
● ○
○●●
往左移动
●○●
○●○
○○●○●
●○
○●●
往右跳
●○●
○●○
○○●○●
○●
○●●
往上移动
●○●
○●○
○○●○
○●●
○●●
往左跳
●○●
○●○
○○ ○●
○●●
○●●
往上跳
●○
○●○
○○●○●
○●●
○●●
往左跳
○●
○●○
○○●○●
○●●
○●●
往下移动
○○●
●○
○○●○●
○●●
○●●
往右跳
○○●
○●
○○●○●
○●●
○●●
往下跳
○○●
○●○
○○●○●
●●
○●●
往下移动
○○●
○●○
○○●○●
○●●
●●
往上跳
○○●
○●○
○○ ○●
○●●
●●●
往上跳
○○
○●○
○○●○●
○●●
●●●
往下移动
○○○
○●
○○●○●
○●●
●●●
往左移动
○○○
○ ●
○○●○●
○●●
●●●
往下移动
○○○
○○●
○ ●○●
○●●
●●●
往右跳
○○○
○○●
○○● ●
○●●
●●●
往左移动
○○○
○○●
○○ ●●
○●●
●●●
往上移动
○○○
○○
○○●●●
○●●
●●●
往下跳
○○○
○○○
○○●●●
●●
●●●
往上移动
○○○
○○○
○○ ●●
●●●
●●●
注意,输出的顺序是反着的
文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/nameofcsdn/article/details/52745351
- 点赞
- 收藏
- 关注作者
评论(0)