一笔画问题
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; }