296 lines
6.4 KiB
C++

#include <iostream>
#include <fstream>
#include <vector>
#include <array>
struct island
{
int L;
int R;
int time;
};
#define LEFT 0
#define FROM_LEFT 1
#define ACROSS 2
#define RIGHT 3
#define FROM_RIGHT 4
#define MAX_NUM 10000000
std::vector<std::array<int, 5>> get_line_combinations(std::vector<island> &line)
{
std::vector<std::array<int, 5>> comp(line.size(), std::array<int, 5>({0}));
if (line.size() == 0)
{
return comp;
}
// going across the line
std::sort(line.begin(), line.end(), [](const island &a, const island &b)
{ return a.time < b.time; });
for (size_t i = 0; i < line.size(); i++)
{
if (i == 0)
{
comp[i][ACROSS] = line[i].time + line[i].L + line[i].R;
}
else
{
comp[i][ACROSS] = comp[i - 1][ACROSS] + line[i].time;
}
}
// going back
std::sort(line.begin(), line.end(), [](const island &a, const island &b)
{ return a.L < b.L; });
std::vector<bool> Lused(line.size(), false);
int most_right_island = 0;
int Lmin = MAX_NUM;
int Lval = 0;
int dist = 0;
int Lindex = 0;
int FLmin = 0;
std::vector<bool> Rused(line.size(), false);
int most_left_island = line.size();
int Rmin = MAX_NUM;
int Rval = 0;
int Rindex = 0;
int FRmin = 0;
int tmp = 0;
for (size_t i = 0; i < line.size(); i++)
{
if (i == 0)
{
for (size_t j = 0; j < line.size(); j++)
{
Lval = line[j].L + line[j].L + line[j].time;
if (Lval < Lmin)
{
Lmin = Lval;
Lindex = j;
FLmin = line[j].L + line[j].time;
}
Rval = line[j].R + line[j].R + line[j].time;
if (Rval < Rmin)
{
Rmin = Rval;
Rindex = j;
FRmin = line[j].R + line[j].time;
}
}
}
else
{
for (size_t j = 0; j < line.size(); j++)
{
if (!Lused[j])
{
if (j < most_right_island)
{
Lval = comp[i - 1][LEFT] + line[j].time;
tmp = comp[i - 1][FROM_LEFT] + line[j].time;
}
else
{
dist = line[j].L - line[most_right_island].L;
Lval = comp[i - 1][LEFT] + dist + dist + line[j].time;
tmp = comp[i - 1][FROM_LEFT] + dist + line[j].time;
}
if (Lval < Lmin)
{
Lindex = j;
Lmin = Lval;
FLmin = tmp;
}
}
if (!Rused[j])
{
if (j > most_left_island)
{
Rval = comp[i - 1][RIGHT] + line[j].time;
tmp = comp[i - 1][FROM_RIGHT] + line[j].time;
}
else
{
dist = line[j].R - line[most_left_island].R;
Rval = comp[i - 1][RIGHT] + dist + dist + line[j].time;
tmp = comp[i - 1][FROM_RIGHT] + dist + line[j].time;
}
if (Rval < Rmin)
{
Rindex = j;
Rmin = Rval;
FRmin = tmp;
}
}
}
}
if (Rindex < most_left_island)
{
most_left_island = Rindex;
}
Rused[Rindex] = true;
comp[i][RIGHT] = Rmin;
Rmin = MAX_NUM;
comp[i][FROM_RIGHT] = FRmin;
if (Lindex > most_right_island)
{
most_right_island = Lindex;
}
Lused[Lindex] = true;
comp[i][LEFT] = Lmin;
Lmin = MAX_NUM;
comp[i][FROM_LEFT] = FLmin;
}
return comp;
}
void print_deb(std::vector<int> &RESULT, std::vector<std::array<int, 2>> &A)
{
for (size_t i = 0; i < RESULT.size(); i++)
{
std::cout << RESULT[i] << " ";
}
std::cout << std::endl
<< std::endl;
for (size_t i = 0; i < A.size(); i++)
{
std::cout << A[i][0] << " " << A[i][1] << std::endl;
}
std::cout << std::endl;
}
void increse(std::vector<std::array<int, 2>> &A)
{
for (size_t i = 0; i < A.size(); i++)
{
A[i][0]++;
A[i][1]++;
}
}
void print_line(std::vector<island> &line)
{
for (size_t i = 0; i < line.size(); i++)
{
std::cout << line[i].L << " " << line[i].time << " " << line[i].R << std::endl;
}
std::cout << std::endl;
}
void print_comp(std::vector<std::array<int, 5>> &comp)
{
for (size_t i = 0; i < comp.size(); i++)
{
std::cout << comp[i][LEFT] << " " << comp[i][FROM_LEFT] << " " << comp[i][ACROSS] << " " << comp[i][RIGHT] << " " << comp[i][FROM_RIGHT] << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char *argv[])
{
std::ifstream in(argv[1]);
if (!in)
{
std::cout << "Cannot open file.\n";
return 1;
}
// N = visina
int N;
// sirina
int M;
// stevilo otokov
int K;
in >> N >> M >> K;
M--;
std::vector<std::vector<island>> map(N, std::vector<island>());
int x, y, t;
for (size_t i = 0; i < K; i++)
{
in >> x >> y >> t;
x--;
y--;
map[x].emplace_back(island{y, M - y, t});
}
in.close();
std::vector<int> RESULT(K + 1, MAX_NUM);
std::vector<std::array<int, 2>> A(K + 1, {MAX_NUM, MAX_NUM});
RESULT[0] = 0;
A[0][0] = 0;
A[0][1] = M;
std::vector<std::array<int, 2>> B = A;
int num_of_islands = 0;
std::vector<std::array<int, 5>> comp = get_line_combinations(map[0]);
num_of_islands = comp.size();
for (size_t i = 0; i < comp.size(); i++)
{
RESULT[i + 1] = std::min(RESULT[i + 1], comp[i][FROM_LEFT]);
B[i + 1][0] = std::min(A[i + 1][0], comp[i][LEFT]);
B[i + 1][1] = std::min(A[i + 1][1], comp[i][ACROSS]);
}
increse(B);
A = B;
int prev = 0;
int tmp_left = 0;
int tmp_right = 0;
int tmp2, tmp3;
for (size_t i = 1; i < map.size(); i++)
{
comp = get_line_combinations(map[i]);
num_of_islands += comp.size();
for (size_t j = 1; j <= num_of_islands && comp.size() > 0; j++)
{
tmp_left = MAX_NUM;
tmp_right = MAX_NUM;
for (size_t k = 0; k < j && k < comp.size(); k++)
{
prev = j - (k + 1);
RESULT[j] = std::min({RESULT[j], A[prev][0] + comp[k][FROM_LEFT], A[prev][1] + comp[k][FROM_RIGHT]});
tmp2 = std::min({A[j][0], A[prev][0] + comp[k][LEFT], A[prev][1] + comp[k][ACROSS]});
if (tmp2 < tmp_left)
{
tmp_left = tmp2;
}
tmp3 = std::min({A[j][1], A[prev][0] + comp[k][ACROSS], A[prev][1] + comp[k][RIGHT]});
if (tmp3 < tmp_right)
{
tmp_right = tmp3;
}
}
B[j][0] = tmp_left;
B[j][1] = tmp_right;
}
increse(B);
A = B;
}
for (size_t i = 1; i < RESULT.size(); i++)
{
std::cout << RESULT[i] << " ";
}
std::cout << std::endl;
return 0;
}