【算法复习二】传统基本算法(分治----残缺棋盘问题)

2024-04-05 01:58

本文主要是介绍【算法复习二】传统基本算法(分治----残缺棋盘问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  问题描述:

  残缺棋盘是一个有2k×2kk≥1)个方格的棋盘,其中恰有一个方格残缺。如图给出k=1时各种可能的残缺棋盘,其中残缺的方格用阴影表示。

残缺棋盘问题就是要用这四种三格板覆盖更大的残缺棋盘。在此覆盖中要求:

        1)两个三格板不能重叠

        2)三格板不能覆盖残缺方格,但必须覆盖其他所有的方格。

         

         小格子数(2k×2k -1)三格板中小格子数3。所以所需要的三格板总数为(2k×2k -1 )/3

  例如,一个4*4的残缺棋盘2k*2k

        以k=2时的问题为例,用二分法进行分解,得到的四个k=1的棋盘。但要注意这四个棋盘,并不都是与原问题相似且独立的子问题。

        因为当如图中的残缺方格在左上部时,第1个子问题与原问题相似,而右上角、左下角和右下角三个子棋盘(也就是图中标识为234号子棋盘),并不是原问题的相似子问题,自然也就不能独立求解了。当使用一个①号三格板覆盖234号三个子棋盘的各一个方格后,我们把覆盖后的方格,也看作是残缺方格(称为残缺方格),这时的234号子问题就是独立且与原问题相似的子问题了。

  问题分析

           从以上例子还可以发现

               当残缺方格在第1个子棋盘,用①号三格板覆盖其余三个子棋盘的交界方格,可以使另外三个子棋盘转化为独立子问题;

               当残缺方格在第2个子棋盘时,则首先用②号三格板进行棋盘覆盖

               当残缺方格在第3个子棋盘时,则首先用③号三格板进行棋盘覆盖

               当残缺方格在第4个子棋盘时,则首先用④号三格板进行棋盘覆盖,这样就使另外三个子棋盘转化为独立子问题。

程序代码思路:

         表示方法:每个三格板需要用同一个数字表示,不同三格板编号不同。

源码:

#include <iostream>
#include <iomanip>
using namespace std;
int board[100][100];  //存放棋盘L型的标号数组;
int tile=1;    // L型骨牌号
void chessBoard(int tr, int tc, int dr, int dc, int size)
{ 
if (size==1)
return;
int t = tile++;     // L型骨牌号
int s = size/2;     // 分割棋盘
//________________________________________________ 覆盖左上角子棋盘
if (dr<tr+s&&dc<tc+s)     // 特殊方格在此棋盘中
chessBoard(tr, tc, dr, dc, s);
else                               // 此棋盘中无特殊方格
{           
board[tr+s-1][tc+s-1]=t; // 用 t 号L型骨牌覆盖右下角
chessBoard(tr,tc,tr+s-1, tc+s-1, s);// 覆盖其余方格
} 
//________________________________________________ 覆盖右上角子棋盘
if (dr < tr + s && dc >= tc + s)     // 特殊方格在此棋盘中
chessBoard(tr, tc+s, dr, dc, s);
else                                  // 此棋盘中无特殊方格
{
board[tr + s - 1][tc + s] = t;   //用t号L型骨牌覆盖左下角
chessBoard(tr, tc+s, tr+s-1, tc+s, s);// 覆盖其余方格
}
//_______________________________________________ 覆盖左下角子棋盘
if (dr >= tr + s && dc < tc + s)  // 特殊方格在此棋盘中
chessBoard(tr+s, tc, dr, dc, s);
else                               // 此棋盘中无特殊方格                       
{
board[tr + s][tc + s - 1] = t;  // 用 t 号L型骨牌覆盖右上角
chessBoard(tr+s, tc, tr+s, tc+s-1, s);// 覆盖其余方格
} 
//__________________________________________________ 覆盖右下角子棋盘
if (dr >= tr + s && dc >= tc + s)  // 特殊方格在此棋盘中
chessBoard(tr+s, tc+s, dr, dc, s);
else 
{
board[tr + s][tc + s] = t;     // 用 t 号L型骨牌覆盖左上角       
chessBoard(tr+s, tc+s, tr+s, tc+s, s); // 覆盖其余方格
}
}
int main()
{
int size,dr,dc;
cout<<"\t\t\t棋盘覆盖问题\n";
cout<<"2^k×2^k 个方格变长size(size=2,4,8,16,32,64):";
cin>>size;
cout<<"分别输入特殊块的行下标dr,列下标dc(0-"<<(size-1)<<"):";
cin>>dr>>dc;
board[dr][dc]=0;
cout<<"棋盘覆盖图:\n";
chessBoard(0, 0, dr, dc, size);
int i,j;
for( i=0;i<size;i++)
{
for( j=0;j<size;j++)
cout<<setw(6)<<board[i][j];//setw(6)//输出量不足6个字符时在左面填充空白 
cout<<endl<<endl;
}
return 0;
}


分治递归执行步骤:

         1)chessBoard(0, 0, 0, 0, 4);

               {          t=1;   s=2;

                        chessBoard(0, 0, 0, 0, 2);

                            {        t=2; s=1;

                                     chessBoard(0, 0, 0, 0, 1);

                                          {          s==1

                                                       return  

                                          }

                                                       以下三步

                                                        将左上角 三格板 用t=2覆盖

                               }

                              return

                                      以下三步 对右上递归  先 用t=1 覆盖左下

                                                          左下递归 先 用t=1 覆盖右上

                                                          右下递归 先 用t=1 覆盖左上

                                      递归处理类似。

                  }

                                    

这篇关于【算法复习二】传统基本算法(分治----残缺棋盘问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/877378

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM