练习23

 
  1. /********************************************************************************
  2.  23. (覆盖问题) 有边长为N(N为偶数)的正方形,请你用N^2/2个长为2,
  3.  宽为1的长方形,将它全部覆盖。编程打印出所有覆盖方法。如:N=4
  4.     ┌─┬──┬─┐            ┌──┬──┐
  5.     │  │    │  │ 1224   │    │    │  1122
  6.     │  ├──┤  │            ├──┼──┤
  7.     │  │    │  │ 1334   │    │    │  3344
  8.     ├─┼──┼─┤            ├──┼──┤
  9.     │  │    │  │ 5668   │    │    │  5566
  10.     │  ├──┤  │            ├──┼──┤
  11.     │  │    │  │ 5778   │    │    │  7788
  12.     └─┴──┴─┘            └──┴──┘
  13.     分析:
  14.     经过观察显然可知:
  15.     找出一个没有被覆盖的1*1的方块,它可以与上,下,左,右相邻的1*1方块组成2*1的覆盖
  16.     方块,而这样的几种情况是没有重复的,所以我们要完成所有的覆盖方法,就等于我们要完
  17.     成这几种情况的覆盖方法,而这几种情况还是一个覆盖问题,所以,我采用分治算法解决!
  18. *********************************************************************************/
  19. #include <stdio.h>
  20. #define N 4
  21. typedef struct
  22. {
  23.     int x;
  24.     int y;
  25.     int d;//方向
  26. } Block;
  27. void Find(int k);
  28. void Cover(int x, int y, int d, int k);
  29. //四种基于某点的覆盖情况
  30. int dx[] = {0,1,0,-1};
  31. int dy[] = {1,0,-1,0};
  32. //保存覆盖结果
  33. Block blk[N*N/2];
  34. //保存显示结果
  35. int map[N][N];
  36. //输出数据文件指针
  37. FILE* fp;
  38. //计数器
  39. int counter = 0;
  40. //输出显示结果到文件cover.txt
  41. void output()
  42. {
  43.     int k;
  44.     int x,y;
  45.     //填充显示矩阵
  46.     for(k=0; k<N*N/2; k++)
  47.     {
  48.         map[blk[k].y][blk[k].x] = k+1;
  49.         map[blk[k].y+dy[blk[k].d]][blk[k].x+dx[blk[k].d]] = k+1;
  50.     }
  51.     //显示矩阵
  52.     for(y=0; y<N; y++)
  53.     {
  54.         for(x=0; x<N; x++)
  55.         {
  56.             fprintf(fp,"%3d",map[y][x]);
  57.         }
  58.         fprintf(fp,"/n");
  59.     }
  60.     fprintf(fp,"/n");
  61. }
  62. //判断该块是否在覆盖范围内
  63. int InArea(int x, int y)
  64. {
  65.     if(x<0)
  66.         return 0;
  67.     if(x>=N)
  68.         return 0;
  69.     if(y<0)
  70.         return 0;
  71.     if(y>=N)
  72.         return 0;
  73.     return 1;
  74. }
  75. //查找某一块是否有重叠
  76. int Search(int x, int y, int k)
  77. {
  78.     int t,flag=0;
  79.     for(t=0; t<k; t++)
  80.     {
  81.         if(x==blk[t].x && y==blk[t].y)
  82.         {
  83.             flag = 1;
  84.             break;
  85.         }
  86.         if(x==blk[t].x+dx[blk[t].d] && y==blk[t].y+dy[blk[t].d])
  87.         {
  88.             flag = 1;
  89.             break;
  90.         }
  91.     }
  92.     return flag;
  93. }
  94. //找出一个没有被覆盖的1*1方块
  95. void Find(int k)
  96. {
  97.     int x,y;
  98.     for(y=0; y<N; y++)
  99.     {
  100.         for(x=0; x<N; x++)
  101.         {
  102.             if(!Search(x,y,k))
  103.             {
  104.                 goto L;
  105.             }
  106.         }
  107.     }
  108.     //分治
  109. L:  Cover(x,y,0,k);
  110.     Cover(x,y,1,k);
  111.     Cover(x,y,2,k);
  112.     Cover(x,y,3,k);
  113. }
  114. //覆盖
  115. void Cover(int x, int y, int d, int k)
  116. {
  117.     int tx,ty;
  118.     tx = x+dx[d];
  119.     ty = y+dy[d];
  120.     if(!InArea(tx,ty) || Search(tx,ty,k))
  121.         return;
  122.     blk[k].x = x;
  123.     blk[k].y = y;
  124.     blk[k].d = d;
  125.     if(k==N*N/2-1)//完成了
  126.     {
  127.         counter ++;
  128.         //输出覆盖结果
  129.         output();
  130.     }
  131.     else{//如果还没完成,继续查找
  132.         Find(k+1);
  133.     }
  134. }
  135. void main()
  136. {
  137.     fp = fopen("cover.txt","w");
  138.     Find(0);
  139.     fprintf(fp,"一共有%d种覆盖方法!",counter);
  140.     fclose(fp);
  141. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值