JAVA用爬山法解决八皇后问题_八皇后问题爬山法实现(C语言)

1 #include

2 #include

3 #include

4 #include

5 //

6 //编程题7 //爬山法(八皇后问题)8 //

9

10

11 //棋子结构体12 //typedef struct Chess * Chess;

13

14 int a[64];//a数组中记录了爬山过程中,每次棋盘碰撞次数的最小值

15 int array_count = 0; //array_count是a数组中的计数器

16 int number = 0;//number为爬山次数

17

18 structGlobal_Collidecount_min19 {20 int mincollidecount[64]; //存放每次搜索后,棋盘上最小碰撞对数。

21 int globalmin = -1;22 }global_collidecount_min;23

24

25

26 typedef struct

27 {28 intposx;29 intposy;30 intcollidecount;31 }Coordinate;32

33

34 typedef struct

35 {36 int value;//存储需要比较的数值

37 Coordinate position[8];//存储棋盘上的坐标。

38 }Chess;39

40 Chess chess;41

42

43 //地图结构体

44 typedef struct

45 {46

47 int map[8][8];48 int collidecount[8][8];49 int collidecount2[8][8];50 int collidecount3[8][8];51 }Map;52

53

54 //C实现键值对(Map功能)

55 typedef struct

56 {57 intkey_x;58 intkey_y;59 intvalue;60 boolkaiguan;61 }Pair;62

63

64

65

66 Pair pair[64];67 Map ditu;68

69

70

71 //初始化地图

72 voidinitmap()73 {74 for (int x = 0; x < 8; x++)75 for (int y = 0; y < 8; y++)76 {77 ditu.map[x][y] = 0;78 ditu.collidecount[x][y] = 0;79 ditu.collidecount2[x][y] = 0;80 ditu.collidecount3[x][y] = 0;81 }82 }83

84

85 //初始化八皇后,按列赋初值

86 voidinitchess()87 {88 inty;89 for (y = 0; y < 8; y++)90 {91 int x = rand() % 8;92 chess.value = 1;93 chess.position[y].posx =x;94 chess.position[y].posy =y;95 chess.position[y].collidecount = 0;96 ditu.map[x][y] = chess.value;//用1表示棋子

97 }98

99

100 }101

102

103 //初始化键值对

104 voidinitpair()105 {106

107 for (int i = 0; i < 63; i++)108 {109 pair[i].key_x = 0;110 pair[i].key_y = 0;111 pair[i].kaiguan = false;112 pair[i].value = 0;113 }114

115 }116

117

118

119

120 //输出地图

121 voidoutmap()122 {123

124 for (int x = 0; x < 8; x++)125 {126 for (int y = 0; y < 8; y++)127 printf("%3.1d", ditu.map[x][y]);128 printf("\n");129 }130 }131

132

133 //输出棋子位置

134 voidoutchess()135 {136

137 for (int x = 0; x < 8; x++)138 {139

140 printf("x=%3.1d,y=%3.1d", chess.position[x].posx, chess.position[x].posy);141 printf("\n");142 }143

144 }145

146

147

148 voidoutmap1()149 {150

151 for (int x = 0; x < 8; x++)152 {153 for (int y = 0; y < 8; y++)154 printf("%3.1d", ditu.collidecount[x][y]);155 printf("\n");156 }157 }158

159

160 voidoutmap2()161 {162

163 for (int x = 0; x < 8; x++)164 {165 for (int y = 0; y < 8; y++)166 printf("%3.1d", ditu.collidecount2[x][y]);167 printf("\n");168 }169 }170

171

172 voidoutmap3()173 {174

175 for (int x = 0; x < 8; x++)176 {177 for (int y = 0; y < 8; y++)178 printf("%3.1d", ditu.collidecount3[x][y]);179 printf("\n");180 }181 }182

183

184

185 //将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;

186 voidresetcollidecount()187 {188 for (int x = 0; x < 8; x++)189 for (int y = 0; y < 8; y++)190 {191 ditu.collidecount[x][y] = 0;192 ditu.collidecount2[x][y] = 0;193 ditu.collidecount3[x][y] = 0;194 }195 }196

197

198 //将存储棋盘中最小碰撞数的pair还原

199 voidresetpair()200 {201

202 for (int i = 0; i < 63; i++)203 {204 pair[i].key_x = 0;205 pair[i].key_y = 0;206 pair[i].kaiguan = false;207 pair[i].value = 0;208 }209

210 }211

212

213 ///

214 ///将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;215 ///将存储棋盘中最小碰撞数的pair还原216 ///

217 voidreset()218 {219 resetcollidecount();220 resetpair();221 }222

223

224

225 //查看是否与棋盘中皇后位置重复

226 int find(int row, intcolumn)227 {228 intm;229 for (m = 0; m < 8; m++)230 {231 int posx =chess.position[m].posx;232 int posy =chess.position[m].posy;233 if ((posx == row) && (posy ==column))234 return 0;235 }236 return 1;237 }238

239

240

241 //随机选取一个最小碰撞数所在的位置,将地图中同列的皇后置0,

242 void randomselect(intposition)243 {244

245 srand((int)time(NULL));246 int x = rand() %position;247 /*printf("%d\t%d\n", x, position);248 printf("%d\n", pair[x].key_y);*/

249 int posx = chess.position[pair[x].key_y].posx;//取得同列皇后的横坐标

250 int posy = chess.position[pair[x].key_y].posy;//取得同列皇后的纵坐标251 //printf("%d\t%d\n", posx, posy);

252 chess.position[pair[x].key_y].posx = pair[x].key_x;//将皇后的横坐标该为最小碰撞数所在的位置的横坐标253 //printf("%d\n", pair[x].key_x);

254 ditu.map[posx][posy] = 0;//将地图中皇后原位置置0

255 ditu.map[pair[x].key_x][pair[x].key_y] = 1;//将地图中皇后新位置置1

256 }257

258

259 //统计棋盘中最小碰撞数的个数,并将最小碰撞数所在位置和值存到pair键值对中

260 void countmin(intmin)261 {262 int position = 0;263 for (int n = 0; n < 8; n++)264 for (int m = 0; m < 8; m++)265 if (ditu.collidecount3[n][m] ==min)266 {267 pair[position].key_x =n;268 pair[position].key_y =m;269 pair[position].kaiguan = true;270 pair[position].value =min;271 position++;272 }273

274 randomselect(position);275 }276

277

278

279

280 //遍历 pair[]数组,找出最小碰撞数

281 intvisit()282 {283

284 intmin, min_x, min_y;285

286 for (min_x = 0; min_x < 8; min_x++)287 {288 for (min_y = 0; min_y < 8; min_y++)289 {290 if(find(min_x, min_y))291 {292 min =ditu.collidecount3[min_x][min_y];293 //printf("%d\n", min);294 //printf("%d\t%d\n", min_x, min_y);

295 break;296 }297 }298 break;299 }300 /*printf("%d\t%d\n", min_x, min_y);301 printf("%d\n", min);*/

302

303

304 for (int i = 0; i < 8; i++)305 for (int j = 0; j < 8; j++)306 if(find(i, j))307 {308 if (min >ditu.collidecount3[i][j])309 min =ditu.collidecount3[i][j];310 }311 //printf("%d\n", min);

312

313 returnmin;314 }315

316

317

318

319

320 intcountcollidecount()321 {322 int row, column, count = 0;323 for (row = 0; row < 8; row++)324 for (column = 0; column < 8; column++)325 if (ditu.collidecount2[row][column] != 0)326 count +=ditu.collidecount2[row][column];327 returncount;328 }329

330

331

332 ///

333 ///对m列的n位置上的棋子进行检测334 ///

335 ///

336 ///

337 void function3(int hang, intlie)338 {339 int collidecount = 0;340 int collidecount2 = 0;341 //行检测

342 for (int count = 0; count < 8; count++)343 {344 intm, n;345 int posx =chess.position[count].posx;346 int posy =chess.position[count].posy;347 //printf("x=%d,y=%d\n", posx, posy);

348 for (m = 0; m < 8; m++)349 {350 if ((ditu.map[posx][m] != 0) && (m !=posy))351 {352 collidecount++;353

354 }355 else

356 continue;357 }358

359

360

361

362 //lie列

363 for (n = 0; n < 8; n++)364 {365 if ((ditu.map[n][posy] != 0) && (n !=posx))366 {367 collidecount++;368 }369 else

370 continue;371 }372

373 //dui'jiao'xian对角线

374

375 n = posx - 1; m = posy + 1;376 { for (; (n != -1) && (m != 8); n--, m++)377 if (ditu.map[n][m] != 0)378 collidecount++;379 }380

381 n = posx + 1; m = posy - 1;382 { for (; (n != 8) && (m != -1); n++, m--)383 if (ditu.map[n][m] != 0)384 collidecount++;385 }386 n = posx - 1; m = posy - 1;387

388 { for (; (n != -1) && (m != -1); n--, m--)389 if (ditu.map[n][m] != 0)390 collidecount++;391 }392

393 n = posx + 1; m = posy + 1;394 { for (; (n != 8) && (m != 8); n++, m++)395 if (ditu.map[n][m] != 0)396 collidecount++;397 ditu.collidecount2[posx][posy] +=collidecount;398 } collidecount = 0;399

400

401

402 }403

404 ditu.collidecount3[hang][lie] =countcollidecount();405

406

407 //置零

408 for (int n = 0; n < 8; n++)409 {410 for (int m = 0; m < 8; m++)411 {412 ditu.collidecount2[n][m] = 0;413 }414 }415

416 }417

418

419

420 ///

421 ///检查同列中其他位置上的碰撞数422 ///

423 voidfunction2()424 {425 for (int n = 0; n < 8; n++)426 for (int m = 0; m < 8; m++)427 {428

429 if (!find(n, m))430 continue;431 else

432 {433 int posx =chess.position[m].posx;434 int posy =chess.position[m].posy;435 ditu.map[posx][posy] = 0;//将第m列的皇后置0

436 ditu.map[n][m] = 1;//将m列的第n个位置变为1

437 chess.position[m].posx =n;438 chess.position[m].posy =m;439 outmap();440 outmap3();441 function3(n, m);//对m列n位置碰撞检测

442 printf("\n");443 ditu.map[posx][posy] = 1; //恢复皇后

444 ditu.map[n][m] = 0;445 chess.position[m].posx =posx;446 chess.position[m].posy =posy;447 }448 }449

450 }451

452

453

454 //碰撞对数检测

455 voidfunction1()456 {457 int collidecount = 0;458

459 //行检测

460 for (int count = 0; count < 8; count++)461 {462 intm, n;463 int posx =chess.position[count].posx;464 int posy =chess.position[count].posy;465 //printf("x=%d,y=%d\n", posx, posy);

466 for (m = 0; m < 8; m++)467 {468 if ((ditu.map[posx][m] != 0) && (m !=posy))469 {470 collidecount++;471

472 }473 else

474 continue;475 }476

477

478

479 //lie列

480 for (n = 0; n < 8; n++)481 {482 if ((ditu.map[n][posy] != 0) && (n !=posx))483 {484 collidecount++;485 }486 else

487 continue;488 }489

490 //对角线检测

491 n = posx - 1; m = posy + 1;492 { for (; (n != -1) && (m != 8); n--, m++)493 if (ditu.map[n][m] != 0)494 collidecount++;495 }496

497 n = posx + 1; m = posy - 1;498 { for (; (n != 8) && (m != -1); n++, m--)499 if (ditu.map[n][m] != 0)500 collidecount++;501 }502 n = posx - 1; m = posy - 1;503

504 { for (; (n != -1) && (m != -1); n--, m--)505 if (ditu.map[n][m] != 0)506 collidecount++;507 }508

509 n = posx + 1; m = posy + 1;510 { for (; (n != 8) && (m != 8); n++, m++)511 if (ditu.map[n][m] != 0)512 collidecount++;513 chess.position[count].collidecount +=collidecount;514 } collidecount = 0;515

516 }517 for (int count = 0; count < 8; count++)518 {519 int posx =chess.position[count].posx;520 int posy =chess.position[count].posy;521 ditu.map[posx][posy] =chess.position[count].collidecount;522 }523

524 }525

526

527

528

529

530 //输出数组

531 void output(int*array)532 {533 for (int i = 0; i <= 63; i++)534 {535 printf("%4.1d", array[i]);536 }537 }538

539

540 voidoutput_globalcollidecount()541 {542 for (int i = 0; i <= 63; i++)543 { //if(global_collidecount_min.mincollidecount[i]!=-1)

544 printf("%4.1d", global_collidecount_min.mincollidecount[i]);545 }546

547 }548

549

550

551 //初始化碰撞数

552 voidinit_globalcollidecount()553 {554 for (int i = 0; i <= 63; i++)555 {556 global_collidecount_min.mincollidecount[i] = -1;557 }558 }559

560

561

562

563

564 //存储棋盘中除皇后位置之外,最小的碰撞数

565 void save_mincollidecount(intglobal_min)566 {567 if (global_collidecount_min.globalmin == -1)568 {569 global_collidecount_min.globalmin =global_min;570 global_collidecount_min.mincollidecount[0] =global_min;571 }572 else

573 {574

575 global_collidecount_min.mincollidecount[number] ==global_min;576

577

578

579 if (global_min

581 }582 }583

584

585

586 //如果碰撞数不小于之前所有棋盘检测的最小碰撞数,返回0,爬山法终止

587 int find_global_collidecount(int global)588 {589

590

591 //global是第一次存入,或者global比global_collidecount_min.globalmin还小

592 if ((global_collidecount_min.globalmin == -1) || (global

599 return 0;600 }601

602

603

604

605 voidHillClimbing()606 {607 intmin;608 initmap(); //初始化地图

609 initpair(); //初始化键值对

610 srand((int)time(NULL)); //随机种子

611 initchess(); //初始化棋盘

612 function1(); //碰撞对数检测

613 function2(); //对除皇后外的其他位置进行碰撞检测,将检测值存于ditu.collidecount3

614 min = visit(); //找出ditu.collidecount3中,皇后之外区域内的最小碰撞数

615

616

617 while (find_global_collidecount(min))//如果碰撞数不小于之前所有棋盘检测的最小碰撞数,返回0,爬山法终止

618 {619 number++;620 countmin(min); //统计棋盘中最小碰撞数的个数,并将最小碰撞数所在位置和值存到pair键值对中

621 reset(); //将地图中的碰撞数ditu.collidecount,ditu.collidecount2,ditu.collidecount3置0;将存储棋盘中最小碰撞数的pair[]还原(置0)

622 function1(); //碰撞对数检测

623 function2(); //检查同列中其他位置上的碰撞数

624 min = visit(); //遍历 pair[]数组,找出最小碰撞数

625 }626 }627

628

629

630 intmain()631 {632 init_globalcollidecount();//初始化碰撞数

633 HillClimbing();//爬山法

634 printf("\n");635 printf("globalmin=%3.1d\n", global_collidecount_min.globalmin);//输出最终的最小碰撞次数

636 output(a);//a数组中记录了爬山过程中,每次棋盘碰撞次数的最小值

637 printf("\n");638 printf("%d", number);//number为爬山次数

639 return 0;640 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值