アルゴリズムの設計と分析のための戦略演習を分割して征服する(パート2)

問題6を解決するために戦略を分割して征服する:ラウンドロビンスケジュール問題

問題の説明

n = 2 ^ kのプレイヤーがラウンドロビンをプレイしたいと仮定して、次の要件を満たすゲームスケジュールを設計します。

  • 各プレイヤーは、他のn-1人のプレイヤーと1回対戦する必要があります
  • 各プレイヤーは1日1回しか競争できません
  • ラウンドロビンで合計n-1日

8人のプレーヤーの例は次のとおりです。
ここに写真の説明を挿入

問題分析

このスケジュールは、最小単位で斜めにコピーすることで生成できることが、サンプル画像から分析できます。私が作成したデモ画像をご覧ください。
ここに写真の説明を挿入

アルゴリズムの実装

#include <iostream>
#include <cmath>
#include <algorithm>

#define N 100
using namespace std;
//存放日程表
int schedule[N][N];
//拷贝方块
void copyBox(int,int,int,int,int);
//生成循环赛日程表
void generateRRS(int);
int main()
{
    
    
    int n;
    cout<<"请输入参加人数:";
    cin>>n;
    generateRRS(n);
    for(int i=0;i<n;i++){
    
    
        for(int j=0;j<n;j++){
    
    
            cout<<schedule[i][j]<<"\t";
        }
        cout<<"\n\n";
    }
    return 0;
}
/*
    拷贝方块实现
    toi,toj为拷贝到的位置的左上角在二维数组中的位置
    fromi,fromj为原始的位置的左上角在二维数组中的位置
    size为拷贝方块的边长
*/
void copyBox(int toi,int toj,int fromi,int fromj,int size){
    
    
    for(int i=0;i<size;i++)
        for(int j=0;j<size;j++)
            schedule[toi+i][toj+j] = schedule[fromi+i][fromj+j];
}
/*
    生成循环赛日程表
    n=2^k,选手个数,参数错误则提示并结束程序
*/
void generateRRS(int n){
    
    

    double temp = log(n)/log(2);
    if(temp != (int)temp || temp == 0){
    
    
        cout<<"函数参数异常!";
        exit(0);
    }

    for(int i=0;i<n;i++)    //初始化第一行
		schedule[0][i]=i+1;

    for(int size=1;size<n;size*=2)
 		for(int i=0;i<n;i+=2*size)	{
    
    
			copyBox(size,size+i,0,i,size);     //左上角拷贝到右下角
			copyBox(size,i,0,size+i,size);     //右上交角拷贝到左下角
		}

}

問題7を解決するための戦略を分割して征服する:特別なボードカバー

問題の説明

  2k×2kの正方形で構成されたチェス盤には、他の正方形とは異なる正方形が1つだけあり、この正方形を特殊正方形と呼び、ボードを特殊チェスボードと呼びます。
  チェスボードカバレッジ問題では、図に示すように4つの異なる形状のL字型ドミノを使用して、特別な正方形を除く特定の特殊チェスボード上のすべての正方形をカバーし、2つのL字型ドミノが重ならないようにします。
  特定の特殊なチェスボードについて、チェスボードのカバレッジスキームを設計します。
    例:
    入力:
      2 // k、チェスボードの辺の長さは2k
      0 1 //特殊な正方形の座標(2k * 2kのマトリックスを使用してチェスボードを表す)
    出力:
     2 0 3 3
     2 2 1 3
     4 1 1 5
     4 4 5 5

問題分析

ここに写真の説明を挿入
上の写真は完成した4 * 4の特別なチェッカーボードカバーです。少し分析してみましょう。整然とカバーしたい場合、問題は次のような十分に小さなサブ問題に分解する
ここに写真の説明を挿入
ことです。同じ番号コードを使用して表現したいので、空のボックスが1つしかない場合、特別な正方形でない場合は、対応するドミノ番号を入力します。
分解では、我々は特別なコーナーで番号を配置する必要があり
  、
  それを追加し
  、左上隅の右下隅、追加
  追加し、右上の左下隅を追加し、右下隅の左上隅を下の右上隅左隅に、そして
継続この戦略は、分解中にも使用されます。
ここに写真の説明を挿入

アルゴリズムの実装

#include <iostream>
#include <cmath>
#include <algorithm>
#define N 100
using namespace std;

//棋盘
int chessboard[N][N];
//骨牌编号
int gno = 0;

//覆盖特殊棋盘函数
void putChessboard(int,int,int,int,int);

int main()
{
    
    
    //棋盘大小
    int n;
    //特殊方格行列号
    int si,sj;

    cout<<"请输入棋盘大小:";
    cin>>n;
    //检测一下n
    double temp = log(n)/log(2);
    if(temp != (int)temp || temp == 0){
    
    
        cout<<"棋盘大小异常!";
        exit(0);
    }

    cout<<"请输入特殊方格位置:";
    cin>>si>>sj;

    putChessboard(0,0,si,sj,n);

    for(int i=0;i<n;i++){
    
    
        for(int j=0;j<n;j++){
    
    
            cout<<chessboard[i][j]<<"\t";
        }
        cout<<"\n\n";
    }
    return 0;
}
/*
    覆盖特殊棋盘函数
    ti,tj 棋盘左上角的坐标
    si,sj 特殊方格的位置
    size 棋盘宽度 不符提示并退出程序
*/
void putChessboard(int ti,int tj,int si,int sj,int size){
    
    
    if(size == 1) return;
    //当前骨牌编号
    int no = ++gno;

    int mSize = size/2; // 分割棋盘

    //处理左上角棋盘
    if(si<ti+mSize && sj<tj+mSize)
        putChessboard(ti,tj,si,sj,mSize);
    else{
    
    
        chessboard[ti+mSize-1][tj+mSize-1] = no;
        putChessboard(ti,tj,ti+mSize-1,tj+mSize-1,mSize);
    }
    //处理左下角棋盘
    if(si>=ti+mSize && sj<tj+mSize)
        putChessboard(ti+mSize,tj,si,sj,mSize);
    else{
    
    
        chessboard[ti+mSize][tj+mSize-1] = no;
        putChessboard(ti+mSize,tj,ti+mSize,tj+mSize-1,mSize);
    }
    //处理右上角棋盘
    if(si<ti+mSize && sj>=tj+mSize)
        putChessboard(ti,tj+mSize,si,sj,mSize);
    else{
    
    
        chessboard[ti+mSize-1][tj+mSize] = no;
        putChessboard(ti,tj+mSize,ti+mSize-1,tj+mSize,mSize);
    }
    //处理右下角棋盘
    if(si>=ti+mSize && sj>=tj+mSize)
        putChessboard(ti+mSize,tj+mSize,si,sj,mSize);
    else{
    
    
        chessboard[ti+mSize][tj+mSize] = no;
        putChessboard(ti+mSize,tj+mSize,ti+mSize,tj+mSize,mSize);
    }
}

このブログの他の記事で推奨されています

アルゴリズムの設計と分析のための戦略演習を分割して征服する(上)

アルゴリズムの設計と分析の戦略を分割して征服する

再帰的アルゴリズム演習のアルゴリズム設計と分析(パート2)

再帰的アルゴリズム演習のアルゴリズム設計と分析(上)

アルゴリズムの設計と分析におけるデジタル三角形の問題

ZOJ2104-のアルゴリズム設計と分析バルーンを上昇させます

優先キューとソリューションZOJ1167のアルゴリズム設計と分析

おすすめ

転載: blog.csdn.net/L333333333/article/details/102640726