1
1
#include < iostream>
2
+ #include < iomanip>
3
+ #include < vector>
4
+ #include < utility>
5
+ #include < cmath>
2
6
3
- int main (){
7
+ using namespace std ;
4
8
5
- }
9
+ struct Vector2 {
10
+ double x=0 , y=0 ;
11
+ Vector2 () : x(0 ), y(0 ){};
12
+ Vector2 (double x, double y) : x(x), y(y){};
13
+ Vector2 (const Vector2& v) = default ;
14
+
15
+ // unary operations
16
+ Vector2 operator -() const { return {-x, -y}; }
17
+ Vector2 operator +() const { return {x, y}; }
18
+
19
+ // binary operations
20
+ Vector2 operator -(const Vector2& rhs) const { return {x - rhs.x , y - rhs.y }; }
21
+ Vector2 operator +(const Vector2& rhs) const { return {x + rhs.x , y + rhs.y }; }
22
+ Vector2 operator *(const double & rhs) const { return {x * rhs, y * rhs}; }
23
+ friend Vector2 operator *(const double & lhs, const Vector2& rhs) { return {lhs * rhs.x , lhs * rhs.y }; }
24
+ Vector2 operator /(const double & rhs) const { return {x / rhs, y / rhs}; }
25
+ Vector2 operator /(const Vector2& rhs) const { return {x / rhs.x , y / rhs.y }; }
26
+ bool operator !=(const Vector2& rhs) const { return (*this - rhs).sqrMagnitude () >= 1.0e-6 ; };
27
+ bool operator ==(const Vector2& rhs) const { return (*this - rhs).sqrMagnitude () < 1.0e-6 ; };
28
+
29
+ // assignment operation
30
+ Vector2& operator =(Vector2 const & rhs) = default ;
31
+ Vector2& operator =(Vector2&& rhs) = default ;
32
+
33
+ // compound assignment operations
34
+ Vector2& operator +=(const Vector2& rhs) {
35
+ x += rhs.x ;
36
+ y += rhs.y ;
37
+ return *this ;
38
+ }
39
+ Vector2& operator -=(const Vector2& rhs) {
40
+ x -= rhs.x ;
41
+ y -= rhs.y ;
42
+ return *this ;
43
+ }
44
+ Vector2& operator *=(const double & rhs) {
45
+ x *= rhs;
46
+ y *= rhs;
47
+ return *this ;
48
+ }
49
+ Vector2& operator /=(const double & rhs) {
50
+ x /= rhs;
51
+ y /= rhs;
52
+ return *this ;
53
+ }
54
+ Vector2& operator *=(const Vector2& rhs) {
55
+ x *= rhs.x ;
56
+ y *= rhs.y ;
57
+ return *this ;
58
+ }
59
+ Vector2& operator /=(const Vector2& rhs) {
60
+ x /= rhs.x ;
61
+ y /= rhs.y ;
62
+ return *this ;
63
+ }
64
+
65
+ double sqrMagnitude () const { return x * x + y * y; }
66
+ double getMagnitude () const { return sqrt (sqrMagnitude ()); }
67
+ static double getMagnitude (const Vector2& vector) { return vector.getMagnitude (); }
68
+
69
+ static double Distance (const Vector2& a, const Vector2& b) { return sqrt ((a.x - b.x ) * (a.x - b.x ) + (a.y - b.y ) * (a.y - b.y )); };
70
+ double Distance (const Vector2& b) const { return sqrt ((x - b.x ) * (x - b.x ) + (y - b.y ) * (y - b.y )); };
71
+ static double DistanceSquared (const Vector2& a, const Vector2& b) { return (a.x - b.x ) * (a.x - b.x ) + (a.y - b.y ) * (a.y - b.y ); };
72
+ double DistanceSquared (const Vector2& b) const { return (x - b.x ) * (x - b.x ) + (y - b.y ) * (y - b.y ); };
73
+
74
+ static Vector2 normalized (const Vector2& v) { return v.normalized (); };
75
+ Vector2 normalized () const {
76
+ auto magnitude = getMagnitude ();
77
+
78
+ // If the magnitude is not null
79
+ if (magnitude > 0 .)
80
+ return Vector2 (x, y) / magnitude;
81
+ else
82
+ return {x, y};
83
+ };
84
+
85
+ static const Vector2 zero;
86
+ };
87
+
88
+ const Vector2 Vector2::zero = {0 , 0 };
89
+
90
+ struct Boid {
91
+ Boid (const Vector2& pos, const Vector2& vel): position(pos), velocity(vel){};
92
+ Boid ():position({0 ,0 }), velocity({0 ,0 }){};
93
+ Vector2 position;
94
+ Vector2 velocity;
95
+ };
96
+
97
+ struct Cohesion {
98
+ double radius;
99
+ double k;
100
+
101
+ Vector2 ComputeForce (const vector<Boid>& boids, int boidAgentIndex) {
102
+ auto agent = boids[boidAgentIndex];
103
+ Vector2 centerOfMass = {0 ,0 };
104
+ int numberOfNeighbors = 0 ;
105
+ for (int i = 0 ; i < boids.size (); i++){
106
+ if (i==boidAgentIndex)
107
+ continue ;
108
+ auto vec = boids[i].position - agent.position ;
109
+ auto magnitude = vec.getMagnitude ();
110
+ if (magnitude < radius && vec != Vector2::zero) {
111
+ centerOfMass += vec;
112
+ numberOfNeighbors++;
113
+ }
114
+ }
115
+ if (numberOfNeighbors>0 ){
116
+ return k * ((centerOfMass/numberOfNeighbors)/radius);
117
+ }
118
+ else
119
+ return {};
120
+ }
121
+ };
122
+
123
+ struct Alignment {
124
+ double radius;
125
+ double k;
126
+
127
+ Vector2 ComputeForce (const vector<Boid>& boids, int boidAgentIndex) {
128
+ auto agent = boids[boidAgentIndex];
129
+ Vector2 avgVelocity = {0 ,0 };
130
+ int numberOfNeighbors = 0 ;
131
+ for (const auto & boid : boids){
132
+ auto displacementVec = boid.position - agent.position ;
133
+ auto magnitude = displacementVec.getMagnitude ();
134
+ if (magnitude < radius) {
135
+ avgVelocity += boid.velocity ;
136
+ numberOfNeighbors++;
137
+ }
138
+ }
139
+ if (numberOfNeighbors>0 ){
140
+ return k * (avgVelocity/numberOfNeighbors);
141
+ }
142
+ else
143
+ return {};
144
+ }
145
+ };
146
+
147
+ struct Separation {
148
+ double radius;
149
+ double k;
150
+ double maxForce;
151
+
152
+ Vector2 ComputeForce (const vector<Boid>& boids, int boidAgentIndex) {
153
+ auto agent = boids[boidAgentIndex];
154
+ Vector2 avg = {0 ,0 };
155
+ int numberOfNeighbors = 0 ;
156
+ for (int i=0 ;i<boids.size ();i++){
157
+ if (i==boidAgentIndex)
158
+ continue ;
159
+ auto displacementVec = boids[i].position - agent.position ;
160
+ auto magnitude = displacementVec.getMagnitude ();
161
+ if (magnitude < radius && displacementVec != Vector2::zero) {
162
+ auto displacementVecNorm = displacementVec / magnitude;
163
+ avg += displacementVecNorm;
164
+ numberOfNeighbors++;
165
+ }
166
+ }
167
+ if (avg.getMagnitude () > maxForce)
168
+ return avg.normalized () * maxForce;
169
+ else
170
+ return avg;
171
+ }
172
+ };
173
+
174
+ int main () {
175
+ // Variable declaration
176
+ double rc, rs, Fsmax, ra, Kc, Ks, Ka;
177
+ int numberOfBoids;
178
+ string line; // for reading until EOF
179
+ vector<Boid> currentState, newState;
180
+ // Input Reading
181
+ cin >> rc >> rs >> Fsmax >> ra >> Kc >> Ks >> Ka >> numberOfBoids;
182
+ for (int i = 0 ; i < numberOfBoids; i++)
183
+ {
184
+ Boid b;
185
+ cin >> b.position .x >> b.position .y >> b.velocity .x >> b.velocity .y ;
186
+ // cout << "b.y: " << b.y << endl;
187
+ currentState.push_back (b);
188
+ newState.push_back (b);
189
+ }
190
+ // Final input reading and processing
191
+ while (getline (cin, line)) { // game loop
192
+ currentState = newState;
193
+ double deltaT = stod (line);
194
+ // cout << "== Start Line Read. deltaT: " << deltaT << " ==" << endl;
195
+ vector<Vector2> allForces; // a vector of the sum of forces for each boid.
196
+ // Compute Forces
197
+ for (int i = 0 ; i < numberOfBoids; i++) // for every boid
198
+ {
199
+ // cout << ">-> For Every Boid " << i << endl;
200
+ double totalForceX = 0.0 , totalForceY = 0.0 , cohesionTotalX = 0.0 , cohesionTotalY = 0.0 ,
201
+ separationTotalVX = 0.0 , separationTotalVY = 0.0 , alignmentTotalVX = 0.0 ,
202
+ alignmentTotalVY = 0.0 ;
203
+ int cohesionTotalBoids = 0 , alignmentTotalBoids = 0 ;
204
+ for (int j = 0 ; j < N; j++) // for every boid combination. Pre-processing loop.
205
+ {
206
+ // cout << ">-> >-> For Every Boid Combination " << j << endl;
207
+ // Pre-Process Cohesion Forces
208
+ if (i != j
209
+ && get_distance (allBoids[i].x , allBoids[i].y , allBoids[j].x , allBoids[j].y ) <= rc) {
210
+ // cout << "Cohesion Force Found" << endl;
211
+ cohesionTotalX += allBoids[j].x ;
212
+ cohesionTotalY += allBoids[j].y ;
213
+ cohesionTotalBoids++;
214
+ }
215
+ // Pre-Process Separation Forces
216
+ if (i != j
217
+ && get_distance (allBoids[j].x , allBoids[j].y , allBoids[i].x , allBoids[i].y ) <= rs) {
218
+ // cout << "Separation Force Found" << endl;
219
+ pair<double , double > nvANi
220
+ = get_normalized_vector (allBoids[j].x , allBoids[j].y , allBoids[i].x , allBoids[i].y );
221
+ pair<double , double > vANi
222
+ = get_vector (allBoids[j].x , allBoids[j].y , allBoids[i].x , allBoids[i].y );
223
+ // cout << "nvANI. x: " << nvANi.first << " y: " << nvANi.second << " vANI. x: " << vANi.first << " y: " << vANi.second << endl;
224
+ if (vANi.first != 0 ) {
225
+ separationTotalVX += nvANi.first / abs (vANi.first );
226
+ }
227
+ if (vANi.second != 0 ) {
228
+ separationTotalVY += nvANi.second / abs (vANi.second );
229
+ }
230
+ // cout << "nvANi.first: " << nvANi.first << " vANi.first: " << vANi.first << " nvANi.first/vANi.first: " << nvANi.first/vANi.first << endl;
231
+ }
232
+ // Pre-Process Alignment Forces
233
+ if (get_distance (allBoids[i].x , allBoids[i].y , allBoids[j].x , allBoids[j].y ) <= ra) {
234
+ // cout << "Alignment Force Found" << endl;
235
+ alignmentTotalVX += allBoids[j].vx ;
236
+ alignmentTotalVY += allBoids[j].vy ;
237
+ alignmentTotalBoids++;
238
+ // cout << "alignmentTotalVX: " << alignmentTotalVX << endl;
239
+ }
240
+ }
241
+ // Process Cohesion Forces
242
+ if (cohesionTotalBoids > 0 ) { // If a cohesion force was found
243
+ pair<double , double > cohesionVector
244
+ = get_vector (allBoids[i].x , allBoids[i].y , cohesionTotalX / cohesionTotalBoids,
245
+ cohesionTotalY / cohesionTotalBoids);
246
+ totalForceX += (cohesionVector.first / rc) * Kc;
247
+ totalForceY += (cohesionVector.second / rc) * Kc;
248
+ // cout << "* cohesion force Y: " << ((cohesionVector.second/rc) * Kc) << endl;
249
+ }
250
+ // Process Separation Forces
251
+ if (sqrt (pow (separationTotalVX, 2 ) * pow (separationTotalVY, 2 ))
252
+ <= Fsmax) // if total force is NOT greater than limit, use as is.
253
+ {
254
+ totalForceX += (separationTotalVX * Ks);
255
+ // cout << "S totalForceY: " << totalForceY << endl;
256
+ totalForceY += (separationTotalVY * Ks);
257
+ // cout << "* (1)separation Force Y: " << totalForceY << endl;
258
+ } else { // else normalize and multiply by limit
259
+ pair<double , double > normalized = normalize_vector (separationTotalVX, separationTotalVY);
260
+ totalForceX += normalized.first * Fsmax * Ks;
261
+ totalForceY += normalized.second * Fsmax * Ks;
262
+ // cout << "* (2)separation Force Y: " << (normalized.second * Fsmax * Ks) << endl;
263
+ }
264
+ // Process Alignment Forces
265
+ if (alignmentTotalBoids > 0 ) {
266
+ totalForceX += alignmentTotalVX / alignmentTotalBoids * Ka;
267
+ // cout << "(A) totalForceX: " << totalForceX << endl;
268
+ totalForceY += alignmentTotalVY / alignmentTotalBoids * Ka;
269
+ // cout << "* total Alignment Force X: " << (alignmentTotalVX/alignmentTotalBoids * Ka) << " totalForceX " << totalForceX << endl;
270
+ }
271
+ // cout << "total Force X in the end: " << totalForceX << endl;
272
+ // cout << "* total Force Y in the end: " << totalForceY << endl;
273
+ // Add total forces of 1 boid to forces vector.
274
+ allForcesX.push_back (totalForceX);
275
+ allForcesY.push_back (totalForceY);
276
+ }
277
+ // Tick Time and Output
278
+ cout << fixed << setprecision (3 ); // set 3 decimal places precision for output
279
+ for (int i = 0 ; i < N; i++) // for every boid
280
+ {
281
+ // cout << "FORCES X: " << allForcesX[i] << " Y: " << allForcesY[i] << endl;
282
+ allBoids[i].vx += allForcesX[i] * deltaT;
283
+ allBoids[i].vy += allForcesY[i] * deltaT;
284
+ allBoids[i].x += allBoids[i].vx * deltaT;
285
+ allBoids[i].y += allBoids[i].vy * deltaT;
286
+ cout << allBoids[i].x << " " << allBoids[i].y << " " << allBoids[i].vx << " "
287
+ << allBoids[i].vy << endl;
288
+ }
289
+ }
290
+
291
+ return 0 ;
292
+ }
0 commit comments