分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
循环赛日常表
2的n次幂支球队打球,否则不适合分治。
2的n次幂支球队,循环比赛,保证每只球队互相都打过一场。纵坐标球队名称,横坐标是第几天,球队1,在七天中分别和234568球队比赛,球队2在七天中依次和1436587球队比赛。
如果像篮球圣诞大战,要给特殊队伍设置比赛,只需要把队的顺序换下,比如湖人本来是2,换成3
根据结果,推导算法。上图中有如下规律
- 假设等分为4个矩阵,矩阵边距4,右上角矩阵,比左上角矩阵,同一行同一列大4,如第一行,右上角第一列是5左上角第一列是1,第二行右上角第2列是5,左上角第2列是1
- 左下角矩阵,比左上角矩阵,同一行同一列大4,如左下角矩阵第二行第一列是6,左上角第二行第一列是2
- 右下角同一行同一列,比左下角小4,如右下角第三行第二列是4,左下角第三行第二列是8
把大矩阵,一分为2,等分为4个矩阵,直到边距为1不能分为止,先依次计算边距为2的左上角、右上角、左下角、右下角,然后递归结束,这就相当于计算出边距为4的左上角,继续计算边距为4的右上角、左下角、右下角,递归结束,这就是计算出边距为8的左上角,继续...
上角、右上角、左下角、右下角,按照这个顺序,因为规律都是依赖左上角
public class SportsSchedule {
/**
* @description 2的n次幂支球队打球,否则不适合分治
* @author PangTiemin
* @param
* @return
* @date 2021/5/10 13:54
*/
public void scheduleTable(int[][]table,int n){
if (n==1){
table[0][0]=1;
}else {
int m = n/2;
//填左上角
scheduleTable(table,m);
//填右上角
//遍历行
for (int i=0;i<m;i++){
//遍历列,n就是当前递归矩阵的边界大小,值不一定是原n
for (int j=m;j<n;j++){
table[i][j]=table[i][j-m]+m;//规律
}
}
//填左下角
for (int i=m;i<n;i++){
for (int j=0;j<m;j++){
table[i][j]=table[i-m][j]+m;
}
}
//填右下角
for (int i=m;i<n;i++){
for (int j=m;j<n;j++){
table[i][j]=table[i][j-m]-m;
}
}
}
}
public static void main(String[] args) {
SportsSchedule sportsSchedule = new SportsSchedule();
int n=8;
int[][] table=new int[n][n];
sportsSchedule.scheduleTable(table,n);
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
System.out.print(table[i][j]+" ");
}
System.out.println();
}
}
}
棋盘覆盖
一下图片矩阵,给定一个特殊点,比如0所在位置,第一行第二列,要求围绕特殊点,使用L型图案将棋盘布满。L型可以倒过来,左右对称,上下相反,比如我画出的3个红色L。
思路也是把大矩阵划分为小矩阵,比如边距为4矩阵划分为4个边距为2矩阵。
因为特殊点肯定会在4个中的一个,剩下的三个矩阵,最里边的点我们将它设置为同一个数字,这样保证最里面的就是一个L型,如下图。
逻辑是:分别判断特殊点是否在左上、右上、左下、右下。如果特殊点在右上角,就递归处理;如果不是,则认为右上角矩阵的左下角是右上角矩阵新的特殊点,给他一个新数字,(如上会跟另外两个矩阵组成一个L),然后将右上角递归处理!这样会让右上角矩阵作为一个新的整体矩阵继续处理。
如果特殊点在左上角、左下角、右下角,逻辑是一样的。
public class ChessBoard {
//边距长度
private int size;
//左上角起始点坐标
private int leftStartRow;
private int leftStartCol;
//特殊点坐标
private int spectialRow;
private int spectialCol;
//L型标志内容,用数字表示
private int type=0;
//棋盘
private int[][]borad;
public ChessBoard(int size, int leftStartRow, int leftStartCol, int spectialRow, int spectialCol) {
this.size = size;
this.leftStartRow = leftStartRow;
this.leftStartCol = leftStartCol;
this.spectialRow = spectialRow;
this.spectialCol = spectialCol;
this.borad = new int[size][size];
}
private void chess(int size, int leftStartRow, int leftStartCol, int spectialRow, int spectialCol){
//size=1不可用继续分治为小问题
if (size==1){
return;
}
//当前递归,置放 L型 的数字,以4为模是只需要3个数字,以56都可以,这样出现的数字会变多
type = type%4+1;
int n = type;
//把棋盘1分为4,分治为更小的棋盘,直到边距为1
int subSize = size/2;
//如果特殊点在左上角矩阵
if (spectialRow<leftStartRow+subSize&&spectialCol<leftStartCol+subSize){
chess(subSize,leftStartRow,leftStartCol,spectialRow,spectialCol);
}else {
//特殊点不在左上角矩阵,就把左上角矩阵的右下角当做是新的特殊点,当前左上角矩阵的特殊点
borad[leftStartRow+subSize-1][leftStartCol+subSize-1]=n;
chess(subSize,leftStartRow,leftStartCol,leftStartRow+subSize-1,leftStartCol+subSize-1);
}
//如果特殊点在右上角
if (spectialRow<leftStartRow+subSize&&spectialCol>=leftStartCol+subSize){
//新矩阵起始点位置变
chess(subSize,leftStartRow,leftStartCol+subSize,spectialRow,spectialCol);
}else {
//特殊点不在右上角矩阵,就把右上角矩阵的左下角当做是新的特殊点,当前右上角矩阵的特殊点
borad[leftStartRow+subSize-1][leftStartCol+subSize]=n;
chess(subSize,leftStartRow,leftStartCol+subSize,leftStartRow+subSize-1,leftStartCol+subSize);
}
//如果特殊点在左下角
if (spectialRow>=leftStartRow+subSize&&spectialCol<leftStartCol+subSize){
//新矩阵起始点位置变
chess(subSize,leftStartRow+subSize,leftStartCol,spectialRow,spectialCol);
}else {
//右上角置为特殊点
borad[leftStartRow+subSize][leftStartCol+subSize-1]=n;
chess(subSize,leftStartRow+subSize,leftStartCol,leftStartRow+subSize,leftStartCol+subSize-1);
}
//如果特殊点在右下角
if (spectialRow>=leftStartRow+subSize&&spectialCol>=leftStartCol+subSize){
//新矩阵起始点位置变
chess(subSize,leftStartRow+subSize,leftStartCol+subSize,spectialRow,spectialCol);
}else {
//左上角置为特殊点
borad[leftStartRow+subSize][leftStartCol+subSize]=n;
chess(subSize,leftStartRow+subSize,leftStartCol+subSize,leftStartRow+subSize,leftStartCol+subSize);
}
}
public void chessResult(){
borad[spectialRow][spectialCol]=this.type;
chess(this.size,this.leftStartRow,this.leftStartCol,spectialRow,spectialCol);
for (int i=0;i<size;i++){
for (int j=0;j<size;j++){
System.out.print(borad[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
ChessBoard chessBoard = new ChessBoard(4,0,0,0,1);
chessBoard.chessResult();
}
}