描述:
给定一个高度为 2000mm 的柜子空间,以及 n 个层板距离柜子底部高度,满足移动层板位置 使得层板等分衣柜的空间。计算所有移动层板的顺序。 层板号自下向上依次排列,1,2..n。层板需要考虑空间位置,不能跨层板移动
给出以下示例:
示例 1
输入:n = 3,zs = 50,60,1000
输出:
3 2 1
示例 2
输入:n = 4,zs = 50,600,700,1000
输出:
1,4,3,2
4,1,3,2
4,3,1,2
4,3,2,1
提示 1:1 <= n <= 10
提示 2:输出结果需要按小到大排
思路:
简单书写思路
思路1:枚举所有可能,依次派出,剩下的即为答案.(未使用)
思路2:使用多叉树进行存储数据,之后使用dfs(深度优先搜索)整理答案.(本帖使用)
思路3:对板号进行划分格子,如在格子最后使用全排列进行整理答案(未使用).
实际代码
对于示例1\示例2代码可以正确输入输出结果,其他测试用例未知.
具体思路,建立多叉树(二叉树形式),首先对于所有层板进行判断,对于可以移动的层板号码小的为初始节点的子节点,号码较大的层板为子节点的兄弟节点,代表可以不让小号层板先移动,转而让大号层板先移动,子节点则为下一次可以移动的层板.
对于输出:使用向量存储数据,同时用栈进行深度优先搜索,对于每一次的搜索结果存入向量,并找出兄弟节点,再次进行dfs.最后格式化输出vector.
#include<iostream>
#include<stack>
#include <vector>
using namespace std;
typedef struct node {
int data;
struct node* son, * bro;
}Node ;
Node* start(int* a,int n);
vector<int> showNode(Node* node);
Node* createson( int* a, int n);
Node* createbro( int* a, int n, int j);
Node* createbro( int* a, int n, int j)
{//建立兄弟节点
Node *s= new Node ;
//node = p;
s->data = NULL;
s->bro = s->son = NULL;
//n为多叉树的层数
for (; j <= n; j++) {
if (a[j + 1] > (2000 / (n + 1) * j) && a[j] < (2000 / (n + 1) * j))
{
int b[15] = { 0 };
for (int i = 0; i < n + 2; i++)
b[i] = a[i];
b[j] = (2000 / (n + 1) * j);
s->data = j;
s->son = createson( b, n);
if (j == n)return s;//如果相等 也就是最后一位则跳出说明没有兄弟节点
s->bro = createbro( a, n, j+1);
return s;
}
}
return s;
}
Node* createson( int* a, int n)
{//建立子节点
Node* s = new Node;
s->data = NULL;
s->bro = s->son = NULL;
//n为多叉树的层数
for (int j = 1; j <= n; j++)
{//遍历判断是否为兄弟结点
if (a[j + 1] > (2000 / (n + 1) * j) && a[j] < (2000 / (n + 1) * j))
{
int b[15] = { 0 };
for (int i = 0; i < n + 2; i++)
b[i] = a[i];
b[j] = (2000 / (n + 1) * j);
s->data = j;
s->son = createson( b, n);
if (j == n)return s;//如果相等 也就是最后一位 则跳出说明没有兄弟节点
//node->bro = node;
s->bro = createbro( a, n, j+1);
//cout << "1";
break;
}
}
return s;
}
Node* start(int* a, int n) {
//a是层板距离 ,n是层板数,也是多叉树的层数
Node* root=new Node;
root->data = 0;
Node* p = new Node;
root->son=p;
p->bro = p->son = NULL;
//n为多叉树的层数
for (int j = 1; j <= n; j++)
//遍历判断是否为兄弟结点
if (a[j + 1] > (2000 / (n + 1) * j) && a[j] < (2000 / (n + 1) * j))
{
int b[15] = { 0 };
for (int i = 0; i < n+2; i++)
b[i] = a[i];
b[j] = (2000 / (n + 1) * j);
p->data = j;
p->son = createson(b,n);
if (j == n)break; //如果相等 也就是最后一位 则跳出说明没有兄弟节点
p->bro = createbro( a, n, j+1);
break;
}
return root;
}
vector<int> showNode(Node* node)
{
//使用vector存储,维护vector vector里即为答案
//深度遍历
vector<int>v;
stack<Node*> s;
stack<Node*>s2;
s.push(node);
while (!s.empty()) {
Node* treeNode = s.top();
if (treeNode->son->data) { s.push(treeNode->son); }
else
{
while (!s.empty()) {
s2.push(s.top());
s.pop();
}
while (!s2.empty()) {
v.push_back(s2.top()->data);
s.push(s2.top());
s2.pop();
}
while (!treeNode->bro->data ) {
s.pop();
treeNode = s.top();
if (treeNode->bro == NULL) {
s.pop();
break; }
}
if (!s.empty()) {
treeNode = s.top();
s.pop();
s.push(treeNode->bro);
}
}
}
return v;
}
int main()
{
/*
//数据输入
int n;
cin >> n;
int a[15] = { 0 };
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
a[n+1] = 2000;
//多叉树方法,遍历时判断 哪几个可以移动,形成节点,最后遍历输出节点. 觉得这个方法可以用
*/
//从1开始存储,不从0开始
int a[5] = { 0,50,60,1000,2000 };
//int a[6] = { 0,50,600,700,1000,2000 };
int n = 3;
Node *root = start(a, n);
vector <int> v=showNode(root->son);
//格式化输出
int q = 0;
for (int i = 0; i < v.size(); i++)
{
cout << v[i];
q++;
if (q == n) { cout << "\n"; q = 0; }
else cout << ",";
}
return 0;
}
如果代码有问题,请在评论区提问.答案纯原创,转载请说明!
以下为运行效果截图
运行之前同步修改数据输入部分
如果测试第一例测试用例就修改为如下格式
树的实际存储(花的很丑勿笑)并不是所有节点都有值,其他颜色为遍历顺序,也就是答案的顺序,如果有其他的测试用例,也可以在评论区给出,右节点为兄弟,左节点为子节点