/*
学习了一种新的解题方法,很巧妙,利用坐标系来解题。
参考:http://blog.csdn.net/nys001/article/details/12637201
*/
1 #include <iostream>
2 #include <fstream>
3 #include <sstream>
4 #include <cstdlib>
5 #include <cstdio>
6 #include <cstddef>
7 #include <iterator>
8 #include <algorithm>
9 #include <string>
10 #include <locale>
11 #include <cmath>
12 #include <vector>
13 #include <cstring>
14 #include <map>
15 #include <utility>
16 #include <queue>
17 #include <stack>
18 #include <set>
19 #include <functional>
20 using namespace std;
21 typedef pair<int, int> PII;
22 typedef long long int64;
23 const int INF = 0x3f3f3f3f;
24 const int modPrime = 3046721;
25 const double eps = 1e-9;
26 const int MaxN = 100010;
27 const int MaxM = 30;
28 const char Opt[4] = { '+', '-', '*', '/' };
29
30 struct Node
31 {
32 int x, y, z;
33 };
34
35
36 /************************************************************************
37 Description : 初始化蜂窝小区信息
38 Prototype : void InitCellularDistrict(int iMaxSeqValue)
39 Input Param : iMaxSeqValue 蜂窝小区的最大值编号,注:编号从1开始
40 Output Param : 无
41 Return Value : 成功返回0,失败返回-1
42 /************************************************************************/
43 map<int, Node> posToCoords;
44 int maxNum = 0;
45 int InitCellularDistrict(int iMaxSeqValue)
46 {
47 if (iMaxSeqValue < 1 || iMaxSeqValue > 100000)
48 {
49 return -1;
50 }
51 maxNum = iMaxSeqValue;
52 Node nd;
53 nd.x = 0;
54 nd.y = 0;
55 nd.z = 0;
56 posToCoords[1] = nd;
57 for (int i = 2; i <= iMaxSeqValue; ++i)
58 {
59 int circleNum = 0;
60 int cnt = 1;
61 while (cnt < i)
62 {
63 ++circleNum;
64 cnt += (6 * circleNum);
65 }
66 int side = (cnt - i) / circleNum;
67 int sdPos = (cnt - i) % circleNum;
68 switch (side)
69 {
70 case 0:
71 {
72 nd.x = circleNum;
73 nd.z = sdPos;
74 nd.y = -nd.x + nd.z;
75 break;
76 }
77 case 1:
78 {
79 nd.z = circleNum;
80 nd.y = sdPos;
81 nd.x = nd.z - nd.y;
82 break;
83 }
84 case 2:
85 {
86 nd.y = circleNum;
87 nd.x = -sdPos;
88 nd.z = nd.y + nd.x;
89 break;
90 }
91 case 3:
92 {
93 nd.x = -circleNum;
94 nd.z = -sdPos;
95 nd.y = nd.z - nd.x;
96 break;
97 }
98 case 4:
99 {
100 nd.z = -circleNum;
101 nd.y = -sdPos;
102 nd.x = nd.z - nd.y;
103 break;
104 }
105 case 5:
106 {
107 nd.y = -circleNum;
108 nd.x = sdPos;
109 nd.z = nd.y + nd.x;
110 break;
111 }
112 default:
113 break;
114 }
115 posToCoords[i] = nd;
116 }
117 return 0;
118 }
119
120 /************************************************************************
121 Description : 计算出蜂窝小区指定两点(编号值)之间的最短距离
122 Prototype : int GetShortestPathLength(int iFirstValue, int iSecondValue)
123 Input Param : iFirstValue 起点编号值, iSecondValue 终点编号值
124 Output Param : 无
125 Return Value : 计算成功返回最短距离,失败返回-1
126 /************************************************************************/
127 int GetShortestPathLength(int iFirstValue, int iSecondValue)
128 {
129 if (iFirstValue < 1 || iFirstValue > maxNum || iSecondValue < 1 || iSecondValue > maxNum)
130 {
131 return -1;
132 }
133 Node nd1 = posToCoords[iFirstValue];
134 Node nd2 = posToCoords[iSecondValue];
135 int arr[3];
136 arr[0] = abs(nd1.x - nd2.x);
137 arr[1] = abs(nd1.y - nd2.y);
138 arr[2] = abs(nd1.z - nd2.z);
139 sort(arr, arr + 3);
140 int rel = arr[0] + arr[1];
141 return rel;
142 }
143
144 /************************************************************************
145 Description : 清空相关信息
146 Prototype : void Clear()
147 Input Param : 无
148 Output Param : 无
149 Return Value : 无
150 /************************************************************************/
151 void Clear()
152 {
153 posToCoords.clear();
154 maxNum = 0;
155 }
156
157 int main()
158 {
159 #ifdef HOME
160 freopen("in", "r", stdin);
161 //freopen("out", "w", stdout);
162 #endif
163
164
165 InitCellularDistrict(60);
166 int rel = (GetShortestPathLength(19, 30)); // 5
167 InitCellularDistrict(60);
168 int rel1 = (GetShortestPathLength(1, 16)); // 2
169
170 #ifdef HOME
171 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
172 _CrtDumpMemoryLeaks();
173 #endif
174 return 0;
175 }