一笔画问题

CellularDistrict.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
using namespace std;

typedef map<int, int> DUSHUMAP;

//结构体tLine表示一条双向的线段
typedef struct
{
    int pot1;
    int pot2;
}tLine;


//一笔画出给定图形
int OneLineDrawMap (int n, tLine *arrLines, int* aDrawline) ;

// 构造度数map
bool BuildMap(int n, tLine* arrLines, DUSHUMAP& mapDuShu);

// 是否存在欧拉回路,存在返回true
bool IsExistOulaHuiLu(int iJiDian, DUSHUMAP mapDuShu);

// 深度优先搜索求解
void DepthFirstSearch(int iStartpoint, int n, DUSHUMAP& mapDuShu, list<int>& listPath, vector<tLine>& vecLine);

// 判断两点之间存不存在边,存在返回true
bool IsLineBetween2Point(int iPointA, int iPointB, vector<tLine> vecLine);

void search(int x,int *ans,int **a,int *d,int &m,int n);

 

CellularDistrict.cpp

#include "CellularDistrict.h"

/************************************************************************
Description  : 一笔画出给定图形
Prototype    : 
 Input Param  : n表示要画的线段的条数
                arrLines表示由多条线段组成的图形,由调用者负责指针的分配,释放和保证合法性
Output Param :     aDrawline输出画线顺序,调用者保证指针合法性,由调用者负责指针的分配,释放和保证合法性
Return Value :     成功返回 0 ,失败返回-1
/************************************************************************/

int OneLineDrawMap (int n, tLine* arrLines, int* aDrawline) 
{
    // 构造度数map,key为节点序号,value为该序号的度数
    DUSHUMAP mapDuShu;
    if (!BuildMap(n, arrLines, mapDuShu))
    {
        cout << "insert into mapDuShu failed!" << endl;
        return -1;
    }

    // 奇点个数
    int iJiDian = 0;

    // 判断是否能一笔画
    if (!IsExistOulaHuiLu(iJiDian, mapDuShu))
    {
        return -1;
    }

    // 选定一个点为起点,欧拉定理,如果有2个点度为奇数,则只能选其中一个作为起点,另一个为终点
    int iStartpoint = 1;
    if (2 == iJiDian)
    {
        for (DUSHUMAP::iterator it = mapDuShu.begin(); it != mapDuShu.end(); it++)
        {
            if (1 == (it->second) % 2)
            {
                iStartpoint = it->first;
                break;
            }
        }
    }

    // 边vector
    vector<tLine> vecLine;
    for (int i = 0; i < n; i++)
    {
        vecLine.push_back(arrLines[i]);
    }

    // 路径list
    list<int> listPath;

    // 深度优先搜索,递归求解路径
    DepthFirstSearch(iStartpoint, n, mapDuShu, listPath, vecLine);

    // 反序输出
    reverse(listPath.begin(), listPath.end());
    for (list<int>::iterator it = listPath.begin(); it != listPath.end(); it++)
    {
        *aDrawline = *it;
        aDrawline++;
    }

    return 0;
}

// 构造度数map
bool BuildMap(int n, tLine* arrLines, DUSHUMAP& mapDuShu)
{
    for (int i = 1; i <= n; i++)
    {
        std::pair<map<int, int>::iterator, bool> PairRev = mapDuShu.insert(map<int, int>::value_type(i, 0));
        if (!PairRev.second)
        {
            return false;
        }
    }
    for (int i = 1; i <= n; i++)
    {
        int iPort1 = arrLines[i - 1].pot1;
        int iPort2 = arrLines[i - 1].pot2;
        for (DUSHUMAP::iterator it = mapDuShu.begin(); it != mapDuShu.end(); it++)
        {
            if ((it->first == iPort1) || (it->first == iPort2))
            {
                (it->second)++;
            }
        }
    }

    // 删除多余的key
    DUSHUMAP mapTemp(mapDuShu);
    for (DUSHUMAP::iterator it = mapDuShu.begin(); it != mapDuShu.end(); it++)
    {
        if (0 == it->second)
        {
            DUSHUMAP::iterator iter = mapTemp.find(it->first);
            mapTemp.erase(iter);
        }
    }
    mapDuShu = mapTemp;
    return true;
}

// 是否存在欧拉回路
bool IsExistOulaHuiLu(int iJiDian, DUSHUMAP mapDuShu)
{
    for (DUSHUMAP::iterator it = mapDuShu.begin(); it != mapDuShu.end(); it++)
    {
        if (1 == (it->second) % 2)
        {
            iJiDian++;
        }
    }

    // 欧拉定理,无向图存在欧拉路的充要条件是恰有0或2个点度为奇数
    if ((1 == iJiDian) || (iJiDian > 2))
    {
        return false;
    }
    return true;
}

// 深度优先搜索求解
void DepthFirstSearch(int iStartpoint, int n, DUSHUMAP& mapDuShu, list<int>& listPath, vector<tLine>& vecLine)
{
    DUSHUMAP::iterator itValue = mapDuShu.find(iStartpoint);
    if (0 == itValue->second)
    {
        // 当前节点度数为0,加入输出队列
        listPath.push_back(iStartpoint);
        return;
    }
    for (int i = 1; i <= (int)mapDuShu.size(); i++)
    {
        if (IsLineBetween2Point(iStartpoint, i, vecLine))
        {
            // 已经遍历过的边删掉
            vector<tLine>::iterator it = vecLine.begin();
            for (; it != vecLine.end(); it++)
            {
                if (((iStartpoint == it->pot1) && (i == it->pot2))
                    || ((i == it->pot1) && (iStartpoint == it->pot2)))
                {
                    break;
                }
            }
            vecLine.erase(it);

            // 已经遍历过的节点度数减1
            (itValue->second)--;
            itValue = mapDuShu.find(i);
            (itValue->second)--;

            // 递归搜索
            DepthFirstSearch(i, n, mapDuShu, listPath, vecLine);
        }
    }

    // 起点最后入队列
    listPath.push_back(iStartpoint);
}

// 判断两点之间存不存在边,存在返回true
bool IsLineBetween2Point(int iPointA, int iPointB, vector<tLine> vecLine)
{
    for (vector<tLine>::iterator it = vecLine.begin(); it != vecLine.end(); it++)
    {
        if (((iPointA == it->pot1) && (iPointB == it->pot2))
            || ((iPointB == it->pot1) && (iPointA == it->pot2)))
        {
            return true;
        }
    }
    return false;
}

 

posted @ 2014-09-02 19:21  罗维  阅读(444)  评论(0编辑  收藏  举报