2019-2-2

//我的天第一次编写竟然这么长,一定有我没找到的方法,啊哈哈哈哈,
/*
北航机试2020/4/13
第二场第二题
*/
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<iostream>
using namespace std;

const int INF = 100000000;

int input[100][4];
int n,computerId;


typedef struct node
{
    int id;
    int type;
    int layer;//寻找祖先节点时,保存layer这个属性
    node* parent;
    node* port1;
    node* port2;
    node* port3;
    node* port4;
}Node,*Tree;

Node* newNode(int id,int type)
{
    Node* temp = (Node*)malloc(sizeof(Node));
    temp->id = id;
    temp->type = type;
    temp->layer = 0;
    temp->parent = temp->port1 = temp->port2 = temp->port3 = temp->port4 = NULL;
    return temp;
}

void createTree(Node* root)//根节点
{
    for(int i = 0;i<n;i++)//寻找父节点为root->id的孩子节点
    {
        if(input[i][2] == root->id)
        {
            Node* temp = newNode(input[i][0],input[i][1]);
            temp->layer = root->layer + 1;
            temp->parent = root;

            //******节点之间的关系,将刚生成的temp和root关联
            if(root->type == 0)//if(temp->type == 0)错误,此外这条语句不写也没关系,下面匹配不到,会default选项
            {
                switch(input[i][3])
                {
                case 1:
                    root->port1 = temp;
                    break;
                case 2:
                    root->port2 = temp;
                    break;
                case 3:
                    root->port3 = temp;
                    break;
                case 4:
                    root->port4 = temp;
                    break;
                default:
                    break;
                }
                createTree(temp);//递归建树,使用新生成的子节点建树
            }

        }

    }

    return ;
}


/*
按照先序遍历的顺序存储打印机
*/
vector<Node*> printer;
void preOrder(Node* root)
{
    if(root)
    {
        if(root->type == 2) printer.push_back(root);
        preOrder(root->port1);
        preOrder(root->port2);
        preOrder(root->port3);
        preOrder(root->port4);
    }
}

Node* findChildPosition(Node* root,int id)
{
    if(root == NULL) return NULL;
    if(root->id == id) return root;

    Node *temp1,*temp2,*temp3,*temp4;
    temp1 = findChildPosition(root->port1,id);
    if(temp1)
        return temp1;
    temp2 = findChildPosition(root->port2,id);
    if(temp2)
        return temp2;
    temp3 = findChildPosition(root->port3,id);
    if(temp3)
        return temp3;
    temp4 = findChildPosition(root->port4,id);
    if(temp4)
        return temp4;

    return NULL;
}


/*
通过寻找公共祖先节点计算最短距离
按照先序遍历的顺序不断更新printer,最后找到的最短的就是printer编号
*/
//使用层数 + 父指针计算
Node* LeastCommonAncient(Node* root,int id1,int id2)
{
    Node* node1 = findChildPosition(root,id1);
    Node* node2 = findChildPosition(root,id2);

    int layer1 = node1->layer;
    int layer2 = node2->layer;

    if(layer1<layer2)
    {
        int c = layer2-layer1;
        while(c--)
        {
            node2 = node2->parent;
        }
    }

    if(layer1> layer2)
    {
        int d = layer1 - layer2;
        while(d--)
        {
            node1 = node1->parent;
        }
    }
    if(node1 == node2) return node1;
    while(node1->parent->id != node2->parent->id)
    {
        node1 = node1->parent;
        node2 = node2->parent;
    }
    return node1->parent;//return node1;//错误写法
}

int minDistance = INF;
int minDistanceId = 0;//最小的id是从1开始
//通过公共祖先节点,computerId和PrinterId得到最小的距离
int getMinDis(Node* node1,Node* ancient,Node* node2)
{
    int sum = 0;
    while(node1->parent != ancient)
    {
        sum++;
        node1 = node1->parent;
    }
    sum++;
    while(node2->parent != ancient)
    {
        sum++;
        node2 = node2->parent;
    }
    sum++;
    return sum;
}
//通过全局变量minDistance和minDistanceId
void getMinPrinterId(Node* root)
{
    Node *computer = findChildPosition(root,computerId);
    for(int i = 0;i<printer.size();i++)
    {
        Node *node = findChildPosition(root,printer[i]->id);
        Node* ancient = LeastCommonAncient(root,computerId,printer[i]->id);
        int d = getMinDis(computer,ancient,node);
        //cout<<d<<endl;
        if(d<minDistance)
        {
            minDistance = d;
            minDistanceId = printer[i]->id;
        }
    }
}

vector<Node*> path;
void printUpToDown(Node* root,Node* temp)
{
    path.push_back(temp);
    while(temp->parent != root)
    {
        path.push_back(temp);
        temp = temp->parent;
    }
    for(int i = path.size()-1;i>=0;i--)
    {
        if(i == 0)
            cout<<path[i]->id<<endl;
        else
            cout<<path[i]->id<<" ";
    }

}

void printDownToUp(Node* root,Node* temp)
{
    cout<<temp->id<<" ";
    while(temp->parent != root)
    {
        cout<<temp->id<<" ";
        temp = temp->parent;
    }
    cout<<root->id<<" ";
}

void print(Node* root)
{
    Node* node1 = findChildPosition(root,computerId);
    Node* node2 = findChildPosition(root,minDistanceId);
    Node* ancient = LeastCommonAncient(root,computerId,minDistanceId);
    printDownToUp(ancient,node1);
    printUpToDown(ancient,node2);
}

int main()
{
    /*
    输入数据
    */
    cin>>n;
    for(int i = 0;i<n;i++)
    {
        cin>>input[i][0]>>input[i][1]>>input[i][2]>>input[i][3];
    }
    cin>>computerId;

    /*
    建树
    */
    //寻找根节点
    int i = 0;
    for(i = 0;i<n;i++)
    {
        if(input[i][2] == 0)
            break;
    }
    //利用根节点建树
    Node* root = newNode(input[i][0],input[i][1]);
    root->layer = 1;
    createTree(root);
    preOrder(root);
    getMinPrinterId(root);
    cout<<minDistanceId<<endl;
    print(root);



/*
    //TEST
    cout<<printer.size()<<endl;
    for(int i = 0;i<printer.size();i++)
    {
        cout<<printer[i]->id<<" ";
    }
    cout<<endl;

    if(findChildPosition(root,9))
        cout<<findChildPosition(root,9)->id<<endl;
    else
        cout<<"Not Find"<<endl;

    cout<<LeastCommonAncient(root,6,8)->id<<endl;
*/


    return 0;
}
/*
IN:
8
1 0 0 0
2 0 1 1
3 0 1 2
4 0 1 3
5 1 4 3
6 1 3 1
7 2 3 2
8 2 3 3
6
OUT:
7
6 3 7
*/

发布了117 篇原创文章 · 获赞 71 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_34686440/article/details/105501497
今日推荐