-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy path补充题目:1072 Gas Station.c
223 lines (196 loc) · 5.78 KB
/
补充题目:1072 Gas Station.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define INF 65535
#define ERROR -1
/* ——————无向图的邻接表定义开始—————— */
#define MaxVertexNum 1010
typedef int Vertex;
typedef int WeightType;
typedef struct ENode *PtrToENode;
struct ENode{
char vertex1[4], vertex2[4];
WeightType dist; // 路的长度
};
typedef PtrToENode Edge;
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV;
WeightType dist; // 路的长度
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];
typedef struct GNode *PtrToGNode;
struct GNode{
int HouseNum; // the total number of houses
/* Candidate存储在house结点后面 */
int Candidate; // the total number of the candidate locations for the gas stations
int Ne;
AdjList G;
};
typedef PtrToGNode LGraph;
LGraph CreateGraph( int HouseNum, int Candidate );
void DestoryGraph( LGraph Graph );
void InsertEdge(LGraph Graph, Edge E);
/* ——————无向图的邻接表定义结束—————— */
int serviceRange;
int solutionIndex;
float minimumDis, averageDis;
bool collected[MaxVertexNum];
WeightType dist[MaxVertexNum];
LGraph BuildGraph();
void init(LGraph Graph);
int FindMinDist(LGraph Graph);
bool checkCandidate(LGraph Graph, int candidateIndex);
void solve(LGraph Graph);
int main()
{
LGraph graph;
graph = BuildGraph();
solve(graph);
DestoryGraph(graph);
return 0;
}
LGraph CreateGraph( int HouseNum, int Candidate )
{
Vertex V;
LGraph Graph;
Graph = (LGraph)malloc(sizeof(struct GNode));
Graph->HouseNum = HouseNum;
Graph->Candidate = Candidate;
Graph->Ne = 0;
for (V = 0; V < (Graph->HouseNum + Graph->Candidate); ++V)
Graph->G[V].FirstEdge = NULL;
return Graph;
}
void DestoryGraph( LGraph Graph )
{
Vertex V;
PtrToAdjVNode Node;
for (V = 0; V < (Graph->HouseNum + Graph->Candidate); ++V) {
while (Graph->G[V].FirstEdge) {
Node = Graph->G[V].FirstEdge;
Graph->G[V].FirstEdge = Node->Next;
free(Node);
}
}
free(Graph);
}
void InsertEdge(LGraph Graph, Edge E)
{
PtrToAdjVNode NewNode;
Vertex V1, V2;
V1 = (E->vertex1[0] == 'G') ? (atoi(E->vertex1 + 1) + Graph->HouseNum) : atoi(E->vertex1);
V2 = (E->vertex2[0] == 'G') ? (atoi(E->vertex2 + 1) + Graph->HouseNum) : atoi(E->vertex2);
--V1; --V2; // 编号都是从1开始的
// 下面这一步必须判断,题目给的数据并没有遵守题意,给出的城市编号有比N大的值,对应最后一个测试点“段错误”,巨坑!!
if (((E->vertex1[0] != 'G') && atoi(E->vertex1) > Graph->HouseNum) ||
((E->vertex2[0] != 'G') && atoi(E->vertex2) > Graph->HouseNum))
return;
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = V2; NewNode->dist = E->dist;
NewNode->Next = Graph->G[V1].FirstEdge;
Graph->G[V1].FirstEdge = NewNode;
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = V1; NewNode->dist = E->dist;
NewNode->Next = Graph->G[V2].FirstEdge;
Graph->G[V2].FirstEdge = NewNode;
}
LGraph BuildGraph()
{
LGraph graph;
Edge E;
int HouseNum, Candidate, i;
scanf("%d %d", &HouseNum, &Candidate);
graph = CreateGraph(HouseNum, Candidate);
scanf("%d", &(graph->Ne));
scanf("%d", &serviceRange);
if (graph->Ne != 0) {
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i < graph->Ne; ++i) {
scanf("%s %s %d", E->vertex1, E->vertex2, &(E->dist));
InsertEdge(graph, E);
}
free(E);
}
return graph;
}
void init(LGraph Graph)
{
Vertex V;
for (V = 0; V < (Graph->HouseNum + Graph->Candidate); ++V) {
collected[V] = false;
dist[V] = INF;
}
}
int FindMinDist(LGraph Graph)
{
Vertex MinV, V;
int MinDist = INF;
for (V = 0; V < (Graph->HouseNum + Graph->Candidate); ++V) {
if (!collected[V] && dist[V] < MinDist) {
MinDist = dist[V];
MinV = V;
}
}
if (MinDist < INF) return MinV;
else return ERROR;
}
bool checkCandidate(LGraph Graph, int candidateIndex)
{
Vertex source, V;
PtrToAdjVNode edge;
double sum, minDis, average;
source = Graph->HouseNum + candidateIndex;
if (!Graph->G[source].FirstEdge) return false;
init(Graph);
// 先将源点放入已取元素的集合中,然后更改其邻接点相关值
collected[source] = true; dist[source] = 0;
for (edge = Graph->G[source].FirstEdge; edge; edge = edge->Next) {
if (edge->dist < dist[edge->AdjV])
dist[edge->AdjV] = edge->dist;
}
// 然后依次从未取元素中找距离最小的元素放入集合中
while (true) {
V = FindMinDist(Graph);
if (dist[V] > serviceRange && V < Graph->HouseNum)
return false;
if (V == ERROR)
break;
collected[V] = true;
for (edge = Graph->G[V].FirstEdge; edge; edge = edge->Next) {
if (!collected[edge->AdjV] && (dist[V] + edge->dist < dist[edge->AdjV])) {
dist[edge->AdjV] = dist[V] + edge->dist;
}
}
}
minDis = INF; sum = 0;
for (V = 0; V < Graph->HouseNum; ++V) {
if (dist[V] == INF) return false;
if (dist[V] < minDis)
minDis = dist[V];
sum += dist[V];
}
average = sum / Graph->HouseNum;
if (minDis > minimumDis || (minDis == minimumDis && average < averageDis)) {
solutionIndex = candidateIndex + 1;
minimumDis = minDis;
averageDis = average;
}
return true;
}
void solve(LGraph Graph)
{
int i;
bool flag = false;
minimumDis = 0;
averageDis = INF;
for (i = 0; i < Graph->Candidate; ++i) {
if (checkCandidate(Graph, i))
flag = true;
}
if (flag) printf("G%d\n%.1lf %.1lf\n", solutionIndex, minimumDis, averageDis);
else printf("No Solution\n");
}