关闭

排列宝石问题回溯算法

标签: 回溯算法宝石排列解空间可行性约束
1566人阅读 评论(0) 收藏 举报
分类:

问题描述:

现有n种不同形状的宝石,每种n颗,共n*n颗。同一形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种颜色。欲将这n*n颗宝石排列成n行n列的一个方阵,使方阵中每一行和每一列的宝石都有n种不同的形状和n种不同颜色。是设计一个算法,计算出对于给定的n,有多少种不同的宝石排列方案。

问题解决:

用回溯算法解决问题的一般步骤为:

step 1、定义一个解空间,它包含问题的解。
step 2、利用适于搜索的方法组织解空间。
step 3、利用深度优先法搜索解空间。
step 4、利用限界函数避免移动到不可能产生解的子空间。

用回溯法解排列宝石问题,用完全n叉树表示解空间,可行性约束place减去不满足要求约束的子树。

<1>、算法思路:

利用回溯算法backtrack,当行号(列号)大于n时,算法搜索至叶节点,当前找到可行性方案,sum+1;否者当前扩展节点是解空间中的内部节点,找出未排列的宝石,用place检验当前宝石是否可以放置,并以深度优先的方式递归的对可行子树搜索。

<2>、算法程序:

#include<iostream>
#include<fstream>
using namespace std;

class Diamond
{
public:
    int color;//颜色编号
    int shape;//形状编号
    int use;//是否已经排列,默认1为未排列
};

 //初始化n*n个宝石
void init(Diamond *a,int n)
{
    //分别为n种颜色各具n种形状的宝石赋初值
    for(int i=1;i<=n*n;i++)
    {
        a[i].color=(i-1)/n+1;
        a[i].shape=(i-1)%n+1;
        a[i].use=1;
    }
}

//检验宝石是否可放
bool place(Diamond *a,int **s,int x,int y)
{
    for(int i=1;i<y;i++)//判断行中是否有颜色形状重复
    {   
        if(a[s[x][i]].color==a[s[x][y]].color || a[s[x][i]].shape==a[s[x][y]].shape)
            return 0;
    }
    for(int j=1;j<x;j++)//判断列中是否有颜色形状重复
    {
        if(a[s[j][y]].color==a[s[x][y]].color || a[s[j][y]].shape==a[s[x][y]].shape)
            return 0;
    }
    return 1;
}

//用回溯法递归搜索
void backtrack(Diamond *a,int **s,int t,int n,int &sum)
{
    int x,y;
    x=(t-1)/n+1;//存放的行号
    y=(t-1)%n+1;//存放的列号
    if(x>n)sum++;
    else
        for(int i=1;i<=n*n;i++)
        {
            if(a[i].use)//当前宝石未排列
            {
                s[x][y]=i;
                if(place(a,s,x,y))//当前宝石颜色形状不重复
                {
                    a[i].use=0;
                    backtrack(a,s,t+1,n,sum);
                    a[i].use=1;
                }
            }
        }
}

//计算当前宝石排列的方案数
int numDiamond(int n)
{
    Diamond *a=new Diamond[n*n+1];
    init(a,n);
    int sum=0;
    int **s=new int*[n+1];
    for(int m=1;m<=n;m++)
        s[m]=new int[n+1];

    backtrack(a,s,1,n,sum);
    return sum;
}

int main()
{
    //读出输入文件中的数据
    fstream fin;
    fin.open("input.txt",ios::in);
    if(fin.fail())
    {
        cout<<"File does not exist!"<<endl;
        cout<<"Exit program"<<endl;
        return 0;
    }

    int n;
    fin>>n;

    //调用函数
    int number=numDiamond(n);
    cout<<"宝石排列的方案数为:"<<number<<"种"<<endl;

    //将结果数据写入到输出文件
    fstream fout;
    fout.open("output.txt",ios::out);
    fout<<number;

    fin.close();
    fout.close();
    system("pause");
    return 0;
}


2
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

排列宝石问题 回溯

问题描述: 现有n种不同形状的宝石,每种n 颗,共n*n颗。同一种形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种 颜色。欲将这n*n颗宝石排列成n行n列的一个方阵,使方阵中每一行...
  • u011980994
  • u011980994
  • 2013-11-27 14:56
  • 1871

排列宝石问题

#include #include #include using namespace std;const int MAX = 50; int n; bool board[MAX][MAX]; //b...
  • u012319493
  • u012319493
  • 2015-11-27 21:42
  • 512

宝石排列问题

西安交大 软件53  蔡少斐 题号:5_10 题目叙述: 现有n种不同形状的宝石,每种n颗,共n*n颗。同一形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种颜色。欲将这n*n颗宝...
  • weixin_37517391
  • weixin_37517391
  • 2017-06-12 10:37
  • 209

拉丁矩阵问题 利用回溯法的C++实现方案

这两天正好在赶算法设计的作业,这里把做的几个需要写代码的题放上来,方便以后查看。 1.题目要求 2.算法思想 这个题目基本思想是 利用回溯法,对于 m 行 n 列, 本质上就是一个二维数...
  • zhyh1435589631
  • zhyh1435589631
  • 2015-05-25 20:53
  • 2135

请教一个n宝石排列问题

现有n种不同形状的宝石,每种n颗,共n2颗。同一种形状的n颗宝石分别具有n种不同的颜色c1,c2,…cn中的一种颜色。欲将这n2颗宝石排列成n行n列的一个方阵,使方阵中每一行和每一列的宝石都有n种不同...
  • cckiller
  • cckiller
  • 2007-03-08 09:35
  • 398

拉丁矩阵 回溯 c java

现有n种不同形状的宝石,每种宝石有足够多颗。欲将这些宝石排列成m行n列的一个矩阵,m n,使矩阵中每一行和每一列的宝石都没有相同形状。试设计一个算法,计算出对于给定的m和n有多少种不同的宝石排列方案。...
  • u011980994
  • u011980994
  • 2013-11-27 15:06
  • 1499

石子合并问题--动态规划;贪心

石子合并问题石子合并问题是最经典的DP问题。首先它有如下3种题型: (1)有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数量。求将这N堆...
  • gatieme
  • gatieme
  • 2015-10-17 20:18
  • 5503

0032算法笔记——【回溯法】电路板排列问题和连续邮资问题

1、电路板排列问题     问题描述      将n块电路板以最佳排列方式插入带有n个插槽的机箱中。n块电路板的不同排列方式对应于不同的电路板插入方案。设B={1, 2, …, n}是n块电路板的...
  • liufeng_king
  • liufeng_king
  • 2013-05-08 10:10
  • 9608

排列宝石问题 回溯

问题描述: 现有n种不同形状的宝石,每种n 颗,共n*n颗。同一种形状的n颗宝石分别具有n种不同的颜色c1,c2,…,cn中的一种 颜色。欲将这n*n颗宝石排列成n行n列的一个方阵,使方阵中每一行...
  • u011980994
  • u011980994
  • 2013-11-27 14:56
  • 1871

一个采用BF算法的宝石迷阵的消除解法

刚学C++编程一个多月,我就是个渣渣啊,算法啊数据结构啊基础为负。 测试输入为 2//有几次测试 4 5//地图规模,4行5列,都是自己输入的,可以更改的 .D.M. .DCAE .A...
  • qq_34479368
  • qq_34479368
  • 2016-04-24 16:19
  • 301
    个人资料
    • 访问:77815次
    • 积分:1258
    • 等级:
    • 排名:千里之外
    • 原创:43篇
    • 转载:1篇
    • 译文:1篇
    • 评论:20条
    最新评论