残缺棋盘

2012-04-05

残缺棋盘的问题要求用3个方格的板(三格板)(triominoes)覆盖残缺棋盘。在此覆盖中,两个三格板不能重叠,三格板不能覆盖残缺方格,但必须覆盖其他所有的方格。在这种限制条件下,所需要的三格板总数为(22k-1)/3。可以验证(22k-1)/3是一个整数。k为0的残缺棋盘很容易被覆盖,因为它没有非残缺的方格,用于覆盖的三格板的数目为0。当k=1时,正好存在3个非残缺的方格,并且这三个方格某一方 向的三格板来覆盖。  

#include <stdio.h>
void TileBoard(int tr,int tc,int dr,int dc,int size);
void OutputBoard(int size);

const n=8;
int tile=1;
int Board[n][n];
void main()
{
TileBoard( 0, 0, 3, 2, n );
OutputBoard( n );
}

void TileBoard(int tr,int tc,int dr,int dc,int size)
{ //覆盖残缺棋盘
if(size==1) return;
int t=tile++, //所使用的三格板的数目
s=size/2;//象限大小
//覆盖左上象限
if(dr<tr+s&&dc<tc+s) //残缺方格位于本象限
TileBoard(tr,tc,dr,dc,s);
else
{ //本象限中没有残缺方格, 把三格板t放在右下角
Board[tr+s-1][tc+s-1]=t;
//覆盖其余部分
TileBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上象限
if(dr<tr+s&&dc>=tc+s) //残缺方格位于本象限
TileBoard(tr,tc+s,dr,dc,s);
else
{ //本象限中没有残缺方格, 把三格板t放在左下角
Board[tr+s-1][tc+s]=t;
//覆盖其余部分
TileBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下象限
if(dr>=tr+s&&dc<tc+s) //残缺方格位于本象限
TileBoard(tr+s,tc,dr,dc,s);
else
{ //把三格板t放在右上角
Board[tr+s][tc+s-1]=t;
//覆盖其余部分
TileBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//覆盖右下象限
if(dr>=tr+s&&dc>=tc+s) //残缺方格位于本象限
TileBoard(tr+s,tc+s,dr,dc,s);
else
{ //把三格板t放在左上角
Board[tr+s][tc+s]=t;
//覆盖其余部分
TileBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
void OutputBoard(int size)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
printf( "%5d", Board[i][j] );
printf( "\n" );
}
}

改进用MFC编辑成颜色输出:

#pragma once
#TileBoard。h
// CTileBoard 命令目标

class CTileBoard : public CObject
{
public:
CTileBoard();
CTileBoard(int tr,int tc,int dr,int dc,int size);
void TileBoard(int tr,int tc,int dr,int dc,int size);
void CopyBoard(int* OtherBoard[]);
void CopyBoard(int OthersBoars[][8]);

void draw(CDC* pDC);
virtual ~CTileBoard();
protected:
static const int n=8;
int tile;
int Board[n][n];

int tr; /*•tr棋盘中左上角方格所在行。*/
int tc; /*•tc棋盘中左上角方格所在列。*/
int dr; /*•dr残缺方块所在行。*/
int dc; /*•dc残缺方块所在列。*/
int size; /*•size棋盘的行数或列数。*/

};
/ TileBoard.cpp : 实现文件
//

#include "stdafx.h"
#include "test.h"
#include "TileBoard.h"


// CTileBoard

CTileBoard::CTileBoard()
{
}
CTileBoard::CTileBoard(int tr,int tc,int dr,int dc,int size)
{
tr=tr;
tc=tc;
dr=dr;
dc=dc;
size=size;
tile=1;
Board[dr][dc]=0;
}
void CTileBoard::TileBoard(int tr,int tc,int dr,int dc,int size)
{
//覆盖残缺棋盘
if(size==1) return;
int t=tile++, //所使用的三格板的数目
s=size/2;//象限大小
//覆盖左上象限
if(dr<tr+s&&dc<tc+s) //残缺方格位于本象限
TileBoard(tr,tc,dr,dc,s);
else
{ //本象限中没有残缺方格, 把三格板t放在右下角
Board[tr+s-1][tc+s-1]=t;
//覆盖其余部分
TileBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上象限
if(dr<tr+s&&dc>=tc+s) //残缺方格位于本象限
TileBoard(tr,tc+s,dr,dc,s);
else
{ //本象限中没有残缺方格, 把三格板t放在左下角
Board[tr+s-1][tc+s]=t;
//覆盖其余部分
TileBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下象限
if(dr>=tr+s&&dc<tc+s) //残缺方格位于本象限
TileBoard(tr+s,tc,dr,dc,s);
else
{ //把三格板t放在右上角
Board[tr+s][tc+s-1]=t;
//覆盖其余部分
TileBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//覆盖右下象限
if(dr>=tr+s&&dc>=tc+s) //残缺方格位于本象限
TileBoard(tr+s,tc+s,dr,dc,s);
else
{ //把三格板t放在左上角
Board[tr+s][tc+s]=t;
//覆盖其余部分
TileBoard(tr+s,tc+s,tr+s,tc+s,s);
}

}
void CTileBoard::draw(CDC* pDC)
{

CBrush *old = pDC->SelectObject(&myBrush);
pDC->Rectangle(0,0,100,100);*/
for (int i=0;i<n;++i)
{
for (int j=0;j<n;++j)
{
CBrush brush(RGB((256/22)*Board[i][j],
(256/22)*Board[i][j],
(256/22)*Board[i][j]));
CBrush* pOldbrush=pDC->SelectObject(&brush);
pDC->Rectangle(i*20,j*20,i*20+19,j*20+19);
pDC->SelectObject(pOldbrush);

}
}
}
void CTileBoard::CopyBoard(int* OtherBoard[])
{
for (int i=0;i<n;++i)
{
for (int j=0;j<n;++j)
{
OtherBoard[i][j]=Board[i][j];
}
}
}
void CTileBoard::CopyBoard(int OthersBoaed[][8])
{
for (int i=0;i<n;++i)
{
for (int j=0;j<n;++j)
{
OthersBoaed[i][j]=Board[i][j];
}
}
}
CTileBoard::~CTileBoard()
{

}
//调用
void CtestView::OnDrawDraw1()
{
CClientDC aDC(this);
CTileBoard* pTileBoard=new CTileBoard(0,0,3,2,8);
pTileBoard->TileBoard(0,0,3,2,8);
pTileBoard->draw(&aDC);
delete pTileBoard;
}





转载于:https://www.cnblogs.com/wkp4666/archive/2012/04/05/2432790.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值