n色方柱问题

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

const int MAX = 50;
int board[MAX][6];  //存储n个立方体各面的颜色
int solu[MAX][6];   //存储解
int n;  //立方体个数、颜色种数
int ans = 0;  //解的个数
int used[MAX];
char color[MAX];

//找到一个解后,输出
void out(int edge[])
{
    int i, j, k, a, b, c, d;
    for(i=0; i<2; i++) //2个子图
    {
        for(j=0; j<n; j++)
            used[j] = 0;
        do{
            j = 0;
            d = c = -1;  
            while(j<n && used[j]>0) //找下一条未用的边
                j++;
            if(j < n)
                do{
                    a = board[j][edge[i*n+j]*2];
                    b = board[j][edge[i*n+j]*2+1];
                    if(b == d)  //如果上一条边的终点与b相同,说明b为始点,交换,保证a为始点
                        swap(a, b);  //保证有向边的始点对应于前面和左面,终点对应于背面和右面
                    solu[j][i*2] = a;
                    solu[j][i*2+1] = b;
                    used[j] = 1;
                    if(c<0)  //开始顶点
                        c = a;
                    d = b; 
                    for(k=0; k<n; k++)  //找下一个立方体
                        if(used[k]==0 && (board[k][edge[i*n+k]*2]==b || board[k][edge[i*n+k]*2+1]==b))
                            j = k;
                }while(b != c);  //找了一圈,回到起点
        }while(j<n);  //所有立方体都找遍
    }
    for(j=0; j<n; j++) //立方体的顶面和底面的颜色
    {
        k = 3 - edge[j] - edge[j+n]; 
        a = board[j][k*2];
        b = board[j][k*2+1];
        solu[j][4] = a;
        solu[j][5] = b;
    }
    for(i=0; i<n; i++)
    {
        for(j=0; j<6; j++)
            cout << color[solu[i][j]] << " ";
        cout << endl;
    }
}

void search()
{
    int i, t, cube;
    bool ok, newg, over;
    int *vert = new int[n];  //记录子图中每个顶点的度,应均为2
    int *edge = new int[n*2];  //记录每个立方体中边被选用的条数,每个立方体只有3条边,有两个子图要选用
    for(i=0; i<n; i++)
        vert[i] = 0;
    t = -1;
    newg = true;
    while(t > -2)
    {
        t++;
        cube = t % n;  //每个立方体找2次,得到真实的立方体编号,也是子图中边的编号
        if(newg)  //如果没有边被选入子图
            edge[t] = -1;  
        over = false;  //是否结束,即两个子图构建完成
        ok = false;    //标记边是否已用过,两个子图不应有公共边
        while(!ok && !over)
        {
            edge[t]++;  //边被选用加入子图,使用次数增加
            if(edge[t]>2)  //在立方体每对相对面的顶点连一条边,每个立方体只有3条边
                over = true;
            else
                ok = (t<n || edge[t]!=edge[cube]);  //是否已用过
        }
        if(!over)
        {          //检测边的两个顶点的度
            if(++vert[board[cube][edge[t]*2]] > 2+t/2*2) //如果是第一个子图,顶点度不能超过2
                ok = false;              //如果是第二个子图,加上第一个子图,顶点度不能超过4
            if(++vert[board[cube][edge[t]*2+1]] > 2+t/2*2)
                ok = false;
            if(t%n == n-1 && ok)  //如果一个或两个子图已构建完成
                for(i=0; i<n; i++)
                    if(vert[i] > 2+t/n*2)
                        ok = false;
            if(ok)
            {
                if(t == n*2-1) //找到解
                {
                    ans++;
                    out(edge);
                    return;
                }
                else
                    newg = true;
            }
            else //取下一条边
            {
                --vert[board[cube][edge[t]*2]];  //边的两个顶点
                --vert[board[cube][edge[t]*2+1]];
                t--;
                newg = false;
            }
        }  
        else //回溯
        {
            t--;
            if(t > -1)
            {
                cube = t % n;
                --vert[board[cube][edge[t]*2]];
                --vert[board[cube][edge[t]*2]];
            }
            t--;
            newg = false;
        }
    }
}

int main()
{
    ifstream fin("n色方柱.txt");
    cout << "输入立方体个数:";
    fin >> n;  cout << n;
    cout << "\n输入颜色:";
    for(int i=0; i<n; i++)
    {
        fin >> color[i];
        cout << color[i] << " ";
    }
    cout << "\n输入立方体各面颜色:\n";
    for(i=0; i<n; i++)
    {
        for(int j=0; j<6; j++)
        {
            fin >> board[i][j];
            cout << board[i][j] << " ";
        }
        cout << endl;
    }

    cout << "\n立方体叠置方案为:\n";
    search();
    if(ans == 0)
        cout << "No Solution!\n";
    cout << endl;
    fin.close();
    return;
}

这里写图片描述

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
回溯法是一种常用的解决组合优化问题的算法。在解决四方柱问题时,可以使用回溯法来找到所有可能的解。 首先,我们可以定义一个递归函数,该函数用于尝试将下一个立方体放置在当前列的上方。在每一步中,我们需要检查当前列的上方是否已经有立方体,并且需要确保上方的立方体的四个面颜与当前立方体的四个面颜都不相同。如果满足这些条件,我们可以将当前立方体放置在上方,并继续递归地尝试下一个立方体。 如果我们成功地将所有立方体都放置在列中,并且每个立方体的四个面颜都不相同,那么我们就找到了一个解。否则,我们需要回溯到上一步,尝试其他可能的放置方式。 以下是一个使用回溯法解决四方柱问题的示例代码: ```python def backtrack(cubes, column): if column == 4: return True for i in range(4): if is_valid(cubes, column, i): cubes[column] = i if backtrack(cubes, column + 1): return True cubes[column] = -1 return False def is_valid(cubes, column, color): for i in range(column): if cubes[i] == color: return False return True cubes = [-1] * 4 backtrack(cubes, 0) print(cubes) ``` 该代码中,`cubes`列表用于存储每个立方体的颜,-1表示该位置还没有放置立方体。`backtrack`函数用于递归地尝试将立方体放置在每一列的上方,`is_valid`函数用于检查当前放置是否满足条件。 运行以上代码,将会输出一个满足条件的立方体颜组合。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值