练习21

  1. /****************************************************************************
  2. 21. 请设计一个程序,由计算机把1.. ̄.8的八个自然数填入图中,使得横、
  3.  竖、对角任何两个相邻的小方格中的两个数是不连续的。(下图右侧的 4 个图
  4.  为禁止的情形).
  5.             ┌─┐          ┌─┐               ┌─┐
  6.             │  │          │4│               │8│
  7.         ┌─┼─┼─┐      └─┼─┐       ┌─┼─┘
  8.         │  │  │  │          │5│       │7│
  9.         ├─┼─┼─┤          └─┘       └─┘
  10.         │  │  │  │      ┌─┐
  11.         └─┼─┼─┘      │6│           ┌─┬─┐
  12.             │  │          ├─┤           │1│2│
  13.             └─┘          │7│           └─┴─┘
  14.                             └─┘ 
  15.             ┌─┐                    
  16.             │t2│                       
  17.         ┌─┼─┼─┐     
  18.         │t4│t0│t6│        
  19.         ├─┼─┼─┤        
  20.         │t7│t1│t5│      
  21.         └─┼─┼─┘   
  22.             │t3│          
  23.             └─┘  
  24. 分析:采用剪枝回溯法
  25. 由于位置的特殊性,将空格按照如下次序搜索.
  26. ******************************************************************************/
  27. #include <stdio.h>
  28. #include <math.h>
  29. //路径集合
  30. static int *t[8];
  31. int t0[] = {1,8,0};//由于位置的特殊性,这里只能放1,8
  32. int t1[] = {1,8,0};//如上类推
  33. int t2[] = {2,7,0};
  34. int t3[] = {2,7,0};
  35. int t4[] = {3,4,5,6,0};
  36. int t5[] = {3,4,5,6,0};
  37. int t6[] = {3,4,5,6,0};
  38. int t7[] = {3,4,5,6,0};
  39. //邻居表
  40. static int *n[8];
  41. int n0[] = {1,2,4,5,6,7,-1};
  42. int n1[] = {0,3,4,5,6,7,-1};
  43. int n2[] = {0,4,6,-1};
  44. int n3[] = {1,5,7,-1};
  45. int n4[] = {0,1,2,7,-1};
  46. int n5[] = {0,1,3,6,-1};
  47. int n6[] = {0,1,2,5,-1};
  48. int n7[] = {0,1,3,4,-1};
  49. //结果的形式
  50. char res[] = "/
  51.             ┌─┐/n/
  52.             │%2d│/n/
  53.         ┌─┼─┼─┐/n/
  54.         │%2d│%2d│%2d│/n/
  55.         ├─┼─┼─┤/n/
  56.         │%2d│%2d│%2d│/n/
  57.         └─┼─┼─┘/n/
  58.             │%2d│/n/
  59.             └─┘/n/
  60. ";
  61. //保存路径
  62. static int Path[8];
  63. //检查合法性
  64. int checked(int k)
  65. {
  66.     int i;
  67.     for(i=0; n[k][i]!=-1; i++)
  68.     {
  69.         if( n[k][i] < k) 
  70.         {
  71.             //如果与邻居数相差1,(不符合)则返回0
  72.             if(abs(t[k][Path[k]]-t[n[k][i]][Path[n[k][i]]]) == 1 )
  73.                 return 0;
  74.         }
  75.     }
  76.     for(i=0; i<k; i++)
  77.     {
  78.         //如果与前面解有重复,(不符合)返回0
  79.         if(t[k][Path[k]] == t[i][Path[i]])
  80.             return 0;
  81.     }
  82.     //符合,返回1
  83.     return 1;
  84. }
  85. //显示结果
  86. void ShowRes()
  87. {
  88.     printf(res, t2[Path[2]],t4[Path[4]],
  89.         t0[Path[0]],t6[Path[6]],t7[Path[7]],
  90.         t1[Path[1]],t5[Path[5]],t3[Path[3]]);
  91. }
  92. //主函数
  93. void main()
  94. {
  95.     int k;
  96.     int flag = 0;
  97.     t[0] = t0;
  98.     t[1] = t1;
  99.     t[2] = t2;
  100.     t[3] = t3;
  101.     t[4] = t4;
  102.     t[5] = t5;
  103.     t[6] = t6;
  104.     t[7] = t7;
  105.     n[0] = n0;
  106.     n[1] = n1;
  107.     n[2] = n2;
  108.     n[3] = n3;
  109.     n[4] = n4;
  110.     n[5] = n5;
  111.     n[6] = n6;
  112.     n[7] = n7;
  113.     for(k=0; k<8; k++)
  114.         Path[k] = -1;
  115.     k=0;
  116.     while(k>=0)
  117.     {
  118.         while(t[k][++Path[k]]!=0)
  119.         {
  120.             if(checked(k) && k<7)
  121.             {
  122.                 //部分解
  123.                 k++;
  124.             }
  125.             else if(checked(k) && k==7)
  126.             {
  127.                 //完全解
  128.                 flag = 1;
  129.                 ShowRes();
  130.                 //回溯,找出所有解
  131.                 Path[k] = -1;
  132.                 k--;
  133.             }
  134.         }
  135.         //回溯
  136.         Path[k] = -1;
  137.         k--;
  138.     }
  139.     //如果没有解
  140.     if(flag == 0)
  141.     {
  142.         printf("no solve!");
  143.     }
  144. }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值