棋盘覆盖问题、半数集问题算法解析-C语言
2015-12-10 20:35
323 查看
问题一:棋盘覆盖问题
对于一个规模为的棋盘,其中有一个方格和其他方格完全不同,称这一方格为特殊方格,且称该棋盘为特殊棋盘,设计一种算法可以使用4种不同的L型骨牌来填充棋牌。
解答:采用分治策略。
第一步:把解决规模为K的棋盘问题分为解决4个规模为K-1的子棋盘问题。若K=1,则返回。
第二步:对于含有特殊方格子棋盘返回第一步。
第三步:将其余子棋盘靠近父棋盘中心的方格设为特殊棋盘,且给予这3个棋盘的特殊方格一个唯一的骨牌号,并返回第一步。
具体算法实现:(基于C语言,VC6.0)
void chessboard(int tr,int tc,int dr,int dc,int size)//tr行号 tc列号
{ int t=tile++,s=size/2;//L棋牌号
if(size==1) return;
//覆盖左上角子棋盘
if((dr<tr+s) && (dc<tc+s))
chessboard(tr,tc,dr,dc,s);//特殊方格在此棋盘
else{
board[tr+s-1][tc+s-1]=t;//特殊方格不在此盘,人工覆盖。
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;
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;
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;
chessboard(tr+s,tc+s,tr+s,tc+s,s);
}
}
程序运行图(骨牌号定义为静态变量,因此与本函数调用的次数一致)
问题二:半数集问题,给定一个自然数N,可以产生半数集set(n),如下
(1)n属于半数集。
(2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半
(3)按此规则处理,直到不能添加半数集为终止。
解答:采用分治策略:
对于求解半数集n的问题,可以分解为求解半数集含n/2和不含n/2的半数集,若n为偶数,对于不含n/2的半数集个数有set(n-2)个,对于含n/2的半数集个数有set(n/2)个。
具体公式如下:
具体算法实现:(基于C语言,VC6.0)
int set(int n)
{ int s;
if(n==1) return 1;
if(n==2) return 2;
//若为偶数
if(n%2==0)
s=set(n-2)+set(n/2);
else //若为奇数
s=set(n-1);
return s;
}
程序运行图
对于一个规模为的棋盘,其中有一个方格和其他方格完全不同,称这一方格为特殊方格,且称该棋盘为特殊棋盘,设计一种算法可以使用4种不同的L型骨牌来填充棋牌。
解答:采用分治策略。
第一步:把解决规模为K的棋盘问题分为解决4个规模为K-1的子棋盘问题。若K=1,则返回。
第二步:对于含有特殊方格子棋盘返回第一步。
第三步:将其余子棋盘靠近父棋盘中心的方格设为特殊棋盘,且给予这3个棋盘的特殊方格一个唯一的骨牌号,并返回第一步。
具体算法实现:(基于C语言,VC6.0)
void chessboard(int tr,int tc,int dr,int dc,int size)//tr行号 tc列号
{ int t=tile++,s=size/2;//L棋牌号
if(size==1) return;
//覆盖左上角子棋盘
if((dr<tr+s) && (dc<tc+s))
chessboard(tr,tc,dr,dc,s);//特殊方格在此棋盘
else{
board[tr+s-1][tc+s-1]=t;//特殊方格不在此盘,人工覆盖。
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;
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;
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;
chessboard(tr+s,tc+s,tr+s,tc+s,s);
}
}
程序运行图(骨牌号定义为静态变量,因此与本函数调用的次数一致)
问题二:半数集问题,给定一个自然数N,可以产生半数集set(n),如下
(1)n属于半数集。
(2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半
(3)按此规则处理,直到不能添加半数集为终止。
解答:采用分治策略:
对于求解半数集n的问题,可以分解为求解半数集含n/2和不含n/2的半数集,若n为偶数,对于不含n/2的半数集个数有set(n-2)个,对于含n/2的半数集个数有set(n/2)个。
具体公式如下:
具体算法实现:(基于C语言,VC6.0)
int set(int n)
{ int s;
if(n==1) return 1;
if(n==2) return 2;
//若为偶数
if(n%2==0)
s=set(n-2)+set(n/2);
else //若为奇数
s=set(n-1);
return s;
}
程序运行图
相关文章推荐
- PAT乙级——1007 A除以B (C/C++)
- PAT乙级——1006 部分A+B (C/C++)
- C/C++的64位整型 不同编译器间的比较(附:各类型数据的范围)
- PAT乙级——1005 德才论 (C/C++)
- PAT乙级——1004 福尔摩斯的约会 (C/C++)
- 解决Visual C++ 编译器中混合 .c 文件时收到 C1853 预编译头错误的方法(转)
- PAT乙级——1003 数素数 (C/C++)
- PAT乙级——1002 数字分类 (C/C++)
- PAT乙级——1001 A+B和C (C/C++)
- 设计模式系列(九)命令模式(Command Pattern)
- 64位windows7 C#.net引用VC++ com组件错误80040154的解决方法
- C++11 学习笔记 模板的细节(右尖括号,using,函数模板默认参数)
- C++ stringstream介绍,使用方法与例子
- c语言知识(找出大于2门成绩不及格的学生)
- C/C++学习(五)冒泡排序
- C++primer学习:随机数.
- C语言简单的菜单选项
- C++报错
- C++设计模式新解二 建造者模式+工厂模式
- effective c++ 学习笔记2