骨牌的棋盘覆盖问题

                                  棋盘覆盖问题


    问题描述:一个正方形棋盘的边长为2^k。在所有棋盘中有一个障碍棋格,请用L型骨牌填充满整个棋盘,其中障碍棋格不能放置骨牌。

    解题思路:使用分治法的思路,棋盘覆盖问题,通过在棋盘的中心位置放置一个L形骨牌,将原问题拆分成四个相同规模的子问题,再对各个子问题递归求解。递归函数的出口为在2*2的棋盘中放置一个L形骨牌。

第一个骨牌为如下放置方法。可以看出原问题被划分为了四个子问题,每个子棋格都存在一个不能放置的棋格。

    接下来再看一下只关注其中一个子问题的解决方法。可以清楚的看到程序在解决问题的过程中一直递归的关注左上角的子问题,最终以解决子问题作为递归出口。

    接下里我们运行一下程序,看一下最终结果。这里我稍微换了一下颜色,障碍棋格用白色表示。

代码:

     我拿QT+c++写的,QT这方面没有做太多注释。

Graph类:

头文件:

#ifndef GRAPH_H

#define GRAPH_H



class Graph

{

public:

int rowCount;

int columnCount;

int **graph;

Graph(int row, int column);

};



#endif // GRAPH_H


源文件:

#include "graph.h"

#include <stdlib.h>


Graph::Graph(int row, int column)

{

rowCount = row;

columnCount = column;

graph = (int**)malloc(sizeof(int*) * rowCount);

for (int i = 0; i < rowCount; i++)

{

graph[i] = (int*)malloc(sizeof(int) * columnCount);

for (int j = 0; j < columnCount; j++)

{

graph[i][j] = 0;

}

}

}


Window类:

头文件:

#ifndef WINDOW_H

#define WINDOW_H


#include <QWidget>

#include <QLabel>

#include <QPicture>

#include <QPainter>

#include <QGridLayout>

//#include <QVBoxLayout>


class Window : public QWidget

{

Q_OBJECT


public:

Window(int** graph, QWidget *parent = nullptr);//根据graph中存放的数据绘制棋盘

~Window();

private:

QLabel *label[16][16];

signals:


public slots:

};


#endif // WINDOW_H


源文件:

#include "window.h"


Window::Window(int** graph, QWidget *parent) : QWidget(parent)

{

QPicture pic[8];

QPainter painter;

//颜色1

painter.begin(&pic[0]);

painter.setBrush(QBrush(QColor(100,100,0)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色2

painter.begin(&pic[1]);

painter.setBrush(QBrush(QColor(0,255,0)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色3

painter.begin(&pic[2]);

painter.setBrush(QBrush(QColor(0,0,255)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色4

painter.begin(&pic[3]);

painter.setBrush(QBrush(QColor(50,100,20)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色5

painter.begin(&pic[4]);

painter.setBrush(QBrush(QColor(255,0,0)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色6

painter.begin(&pic[5]);

painter.setBrush(QBrush(QColor(255,255,0)));

painter.drawRect(0,0,30,30);

painter.end();

//颜色7

painter.begin(&pic[6]);

painter.setBrush(QBrush(QColor(0,255,255)));

painter.drawRect(0,0,30,30);

painter.end();

//白色(障碍棋格)

painter.begin(&pic[7]);

painter.setBrush(QBrush(QColor(255,255,255)));

painter.drawRect(0,0,30,30);

painter.end();


QGridLayout *gridlayout = new QGridLayout();

gridlayout->setMargin(0);

gridlayout->setSpacing(0);

this->setLayout(gridlayout);


for (int i = 0; i < 16; i++)

{

for (int j = 0; j < 16; j++)

{

label[i][j] = new QLabel(this);

if (graph[i][j] == 1)

label[i][j]->setPicture(pic[7]);

else

label[i][j]->setPicture(pic[graph[i][j] % 7]);

label[i][j]->setScaledContents(true);

label[i][j]->setMaximumSize(30,30);

}

}


for (int i = 0; i < 16; i++)

{

for (int j = 0; j < 16; j++)

{

gridlayout->addWidget(label[i][j], i ,j);

}

}


}


Window::~Window()

{


}


主函数:

#include "window.h"

#include <QApplication>

#include "graph.h"

#include <cstdlib>

#include <ctime>


//递归函数(fun)声明

//graph:存放整个棋盘信息的二维数组 rowBegin:关注问题的起始行坐标  columnBegin:关注问题的列坐标 edge:关注问题的棋盘边长 countp:计数器指针

void fun(int ** graph, int rowBegin, int columnBegin, int edge, int *countp);


int main(int argc, char *argv[])

{

QApplication a(argc, argv);


Graph *graph = new Graph(16,16);//创建16*16的棋盘

srand((int)time(0));

graph->graph[rand() % 16][rand() % 16] = 1;//在16*16的棋盘中随机选择一个棋格不能放置骨牌


int count = 1;//计数器:计数所放置的骨牌数

int *countp = &count;//计数器指针

fun(graph->graph,0,0,16,countp);//传入递归函数


Window *w = new Window(graph->graph);

w->show();


return a.exec();

}


void fun(int ** graph, int rowBegin, int columnBegin, int edge, int *countp)

{

if (edge == 2)//递归出口

{

for (int i = 0; i < 2; i++)

{

for (int j = 0; j < 2; j++)

{

if (graph[rowBegin + i][columnBegin + j] == 0)

graph[rowBegin + i][columnBegin + j] = *countp + 1;

}

}

(*countp)++;//计数器+1

}

else

{

int rowIndex = -1;

int columnIndex = -1;

//寻找不能放置骨牌的棋格,其坐标存入rowIndex与columnIndex中

for (int i = 0; i < edge; i++)

{

for (int j = 0; j < edge; j++)

{

if (graph[rowBegin + i][columnBegin + j] != 0)

{

rowIndex = i;

columnIndex = j;

}

}

}


//在棋盘中心给出放置一个L形骨牌

if (rowIndex >= edge / 2)

{

graph[rowBegin + edge / 2 - 1][columnBegin + edge / 2 - 1] = *countp + 1;

graph[rowBegin + edge / 2 - 1][columnBegin + edge / 2] = *countp + 1;

}

else

{

graph[rowBegin + edge / 2][columnBegin + edge / 2 - 1] = *countp + 1;

graph[rowBegin + edge / 2][columnBegin + edge / 2] = *countp + 1;

}


if (columnIndex >= edge / 2)

{

graph[rowBegin + edge / 2 - 1][columnBegin + edge / 2 - 1] = *countp + 1;

graph[rowBegin + edge / 2][columnBegin + edge / 2 - 1] = *countp + 1;

}

else

{

graph[rowBegin + edge / 2 - 1][columnBegin + edge / 2] = *countp + 1;

graph[rowBegin + edge / 2][columnBegin + edge / 2] = *countp + 1;

}

(*countp)++;


//将原问题划分为子问题递归求解

fun(graph,rowBegin, columnBegin, edge / 2, countp);

fun(graph,rowBegin, columnBegin + edge / 2, edge / 2, countp);

fun(graph,rowBegin + edge / 2, columnBegin, edge / 2, countp);

fun(graph,rowBegin + edge / 2, columnBegin + edge / 2, edge / 2, countp);


}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351