首页 > 编程语言 >分治算法(C语言)

分治算法(C语言)

时间:2023-11-05 19:58:04浏览次数:37  
标签:int 分治 tr C语言 算法 棋盘 dr tc oldN

一、棋盘覆盖问题

1、问题

2、分析

  (1)当k>0时,将2k×2k棋盘分割为4个(2k-1)×(2k-1)子棋盘,如图(a)所示。每一次分解,都将原本大小的棋盘,划分为四份,即行号和列号各自缩减一半。

  (2)特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。

  (3)为将无特殊方格子棋盘转化为特殊棋盘,可以用一个骨牌覆盖3个较小棋盘的会合处,如图(b)所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。即:将骨牌的三个部分分别仿作特殊方格子

  (4)递归地使用这种分割,直至棋盘简化为棋盘1×1

 

3、代码分析

 

  (1)入口参数

 

  tr,tc表示当前棋盘的左上角的坐标(tr,tc)

  dr,dc表示特殊方格的坐标(dr,dc)

 

  (2)判断特殊方块在相对于当前棋盘的中心(tr+s,tr+s)哪个位置:

  如果在左上,即有(dr<tr+s,dc<tc+s),若不在,则将(tr+s-1,tc+s-1)涂黑

 

  如果在左下,即有(dr≥tr+s,dc<tc+s),若不在,则将(tr+s,tc+s-1)涂黑

 

  如果在右上,即有(dr<tr+s,dc≥tc+s),若不在,则将(tr+s-1,tc+s)涂黑

 

  如果在右上,即有(dr≥tr+s,dc≥tc+s),若不在,则将(tr+s,tc+s)涂黑

 

  如果在,则传入对应特殊方格位置,并缩小规模

4、代码实现

 

/*棋盘覆盖问题(分治算法)*/
#include<iostream>
#include<algorithm>
using namespace std;
//L型骨牌的编号(递增)
int title=65;
//棋盘 
int Board[10][10];
/*函数形参说明:
  tr:当前棋盘左上角的行号 
  tc:当前棋盘左上角的列号 
  dr:当前特殊方格所在的行号 
  dc:当前特殊方格所在的列号*/
void ChessBoard(int tr,int tc,int dr,int dc,int size) {
    if(size == 1)
        return;
    /*编号加1,且每执行1次,即将原本的棋盘划分成原来的1/4*/
    int t=title++;
    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;
        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);
    }
}
int main() {
    int size=8;
    int index_x=3;
    int index_y=4;
    ChessBoard(0,0,index_x-1,index_y-1,size);
    for(int i=0;i<size;i++){
        for(int j=0;j<size;j++)
            cout << (char)Board[i][j] << ' ';
        cout << endl;
    }
    system("pause");
    return 1;
} 

二、循环日程问题

1、问题

  设有n=2k个选手要进行网球循环赛,设计一个满足以下要求的比赛日程表:

  (1)每个选手必须与其他n-1个选手各赛一次

  (2)每个选手一天只能比赛一次

  (3)循环赛在n-1天结束

2、分析

 

  规律:(1)左上 = 右下    左下 = 右上

     (2)左下的值 = 左上的值 + oldN (n0 = 2,n = oldNnum)

3、代码分析

  按照左下、右上、右下的遍历次序进行遍历oldN=n,n=oldN*2

  (1)左下,行号遍历范围为[oldN+1,n],列号遍历范围为[1,oldN]

  (2)右上,行号遍历范围为[1,oldN],列号遍历范围为[oldN+1,n]

  (3)右下,行号遍历范围为[oldN+1,n],列号遍历范围为[oldN+1,n]

4、代码实现

/*循环日程问题(分治算法)*/
#include<iostream>
#include<algorithm>
using namespace std;
int a[1000][1000];
/*   (i,j)     (i,j+oldN)     (i,j+2oldN)
  (i+oldN,j)   (i+oldN,j)   (i+2oldN,j+2oldN)*/
void Plan(int k) {
    int i,j,oldN,n;
    int num=1;
    /*原始规模为2,每次规模行和列均‘*2’*/
    n=2;
    a[1][1]=1;
    a[1][2]=2;
    a[2][1]=2;
    a[2][2]=1;
    /*迭代处理‘2^k’中情况*/
    while(num<k) {
        oldN=n;
        //右区间的边界 
        n=n*2;
        //左下角 
        for(i=oldN+1;i<=n;i++)
            for(j=1;j<=oldN;j++)
                a[i][j]=a[i-oldN][j]+oldN;
        //右上角(与左下角一致) 
        for(i=1;i<=oldN;i++)
            for(j=oldN+1;j<=n;j++)
                a[i][j]=a[i+oldN][j-oldN];
        //右下角(与左上角一致) 
        for(i=oldN+1;i<=n;i++)
            for(j=oldN+1;j<=n;j++)
                a[i][j]=a[i-oldN][j-oldN];
        num++;
    }
}
int main() {
    int k=3;
    Plan(k);
    int num=1;
    for(int i=1;i<=k;i++)
        num *= 2;
    for(int i=1;i<=num;i++) {
        for(int j=1;j<=num;j++) {
            cout << a[i][j] << "\t";
        }
        cout << endl;
    }
    system("pause");
    return 1;
}

标签:int,分治,tr,C语言,算法,棋盘,dr,tc,oldN
From: https://www.cnblogs.com/Auion-idiot/p/17811005.html

相关文章

  • 【进阶算法】差分
    差分是一种类似于前缀和的编码技巧,可以快速实现对数组某个区间的所有元素增加或减少一个值。一、差分数组示例:数组arr=[8,1,3,-2,5,0,-3,6],输入m个操作,每个操作输入(L,R,val),表示对数组的[L,R]区间中每个元素增加val,要求输出最后的arr数组。比如,第1次操作,输入(0,2......
  • 排序算法
    快速排序......
  • 文心一言 VS 讯飞星火 VS chatgpt (128)-- 算法导论11.1 3题
    三、用go语言,试说明如何实现一个直接寻址表,表中各元素的关键字不必都不相同,且各元素可以有卫星数据。所有三种字典操作(INSERT、DELETE和SEARCH)的运行时间应为O(1)(不要忘记DELETE要处理的是被删除对象的指针变量,而不是关键字。)文心一言,代码正常运行:在Go语言中,我们可以使......
  • ACM竞赛常用算法模板(C++)
    1.快速排序AcWing785.快速排序:https://www.acwing.com/problem/content/787/题目描述给定你一个长度为n的整数数列。请你使用快速排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。输入格式输入共两行,第一行包含整数n。第二行包含n个整数(所有整数均在1∼10......
  • 数据结构与算法—绪论
    前言数据结构与算法是程序员内功体现的重要标准之一,且数据结构也应用在各个方面,业界更有程序=数据结构+算法这个等式存在。各个中间件开发者,架构师他们都在努力的优化中间件、项目结构以及算法提高运行效率和降低内存占用,在这里数据结构起到相当重要的作用。此外数据结构也蕴含一......
  • 算法进阶
    贪心算法定义是指在对问题求解时,总是做出当前看来是最好的选择,着眼于眼前(做出目前对自己好的:贪心),不从整体最优上考虑,做出某种意义上的局部最优解。但有时贪心算法的解就是最优解。要会判断一个问题是否用贪心算法来计算。例题找零问题:假设商店老板需要找零n元钱,钱币的面额有:1......
  • SATA基础+更改终端颜色+PCI.ids位置+Linux和Windows的scanf+C语言C++的局部变量与全局
    SATA基础https://zhuanlan.zhihu.com/p/554251608物理信号物理层功能时钟恢复:对于高频传输,一般是采用差分信号传输,并且没有单独的时钟,时钟存在于编码内部串并转换:对于高频传输,串联信号可以做到更高的频率。字节对其:8/10编码转换的10bit对其链路层、传输层链路层和传输......
  • 试验3 c语言函数应用编程
    实验任务1源代码1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN8067voidprint_text(intline,intcol,chartext[]);8voidprint_spaces(intn);9voidprint_blank_lines(intn)......
  • 排序算法
    一、选择排序12,23,8,15,33,24,77,558,23,12,15,33,24,77,558,12,23,15,33,24,77,558,12,15,23,33,24,77,558,12,15,23,24,33,77,558,12,15,23,24,33,55,77二、冒泡排序12,23,8,15,33,24,77,5512,23,8,15,33,24,55,7712,23,8,15,24,33,55,7712,8,23,15,24,33,55,7712,8,15,23,......
  • 实验3 C语言函数应用编程
    一、实验目的二、实验准备三、实验内容1.实验任务1源代码:1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN8067voidprint_text(intline,intcol,chartext[]);//函数声明8voidprint_spaces(in......