#include <iostream>
#include <vector>
#include <cstdint>
#include <tuple>
#include <algorithm>
#include <array>
typedef std::vector<std::vector<std::uint64_t>> MapType;
typedef std::tuple<std::int64_t, std::int64_t> Point;
typedef std::vector<Point> FootPrint;
int Pa = 2;
std::uintmax_t PoorSearch(const MapType& M, const Point& Fst, const Point& Last) {
std::uintmax_t W = 0;
std::int64_t i = 0;
std::size_t j = 0;
for (j= std::get<1>(Fst);j != std::get<1>(Last); j += (std::get<1>(Fst) - std::get<1>(Last)) ? 1 : -1) {
W += M[j][std::get<0>(Fst)];
}
for (i = std::get<0>(Fst); i != std::get<0>(Last); i += (std::get<0>(Fst) - std::get<0>(Last)) ? 1 : -1) {
W += M[j-1][i];
}
return W;
}
/**/
bool SearchPath_r(const MapType& M, FootPrint FP, const Point& Now, const Point& Last, const std::uintmax_t& Wait, std::intmax_t& Min,FootPrint& FPR) {
static std::array<int, 4> XP = { 0,1,0,-1 };
static std::array<int, 4> YP = { 1,0,-1,0 };
static std::uintmax_t C = 0;
auto X1 = std::get<0>(Now);
auto Y1 = std::get<1>(Now);
auto X2 = std::max<int>(std::get<0>(Last), 0);
auto Y2 = std::max<int>(std::get<1>(Last), 0);
if ((X1 == X2) && (Y1 == Y2)) {
if (Min >= Wait) {
FP.push_back({ X1,Y1 });
Min = Wait;
C++;
FPR = FP;
}
}
if (Min <= Wait) {
return false;
}
FP.push_back({ std::get<0>(Now),std::get<1>(Now) });
for (std::size_t i = 0; i < 4; i++) {
if (std::get<0>(Now) + XP[i] < 0) { continue; };
if (std::get<1>(Now) + YP[i] < 0) { continue; };
if (std::get<0>(Now) + XP[i] >= M.front().size() ) { continue; }
if (std::get<1>(Now) + YP[i] >= M.size()) { continue; }
auto it = std::find_if(FP.begin(), FP.end(), [&](auto& o) {return (std::get<0>(o) == std::get<0>(Now) + XP[i]) && (std::get<1>(o) == std::get<1>(Now) + YP[i]); });
if (it != FP.end()) { continue; }
SearchPath_r(M, FP,{ std::get<0>(Now) + XP[i],std::get<1>(Now) + YP[i] }, Last, Wait + M[std::get<1>(Now) + YP[i]][std::get<0>(Now) + XP[i]], Min,FPR);
}
FP.pop_back();
return true;
}
std::tuple<std::uintmax_t,FootPrint> SearchPath(const MapType& M, const Point& Fst, const Point& Last) {
std::intmax_t Min = PoorSearch(M, Fst, Last);
FootPrint fp;
FootPrint FPR;
//fp.push_back({ 0,0 });
//ESS::Locate(std::get<0>(Fst)+Pa, std::get<1>(Fst)+Pa);
//std::cout << '*';
SearchPath_r(M, fp, Fst, Last, 0, Min,FPR);
return { Min,FPR };
}
typedef std::tuple<Point, std::int64_t,std::uintmax_t,std::uintmax_t> FootData;//pos,dir,weight,now_weight
typedef std::vector<FootData> FootPrint2;
std::tuple<std::uintmax_t, FootPrint2> SearchPathL(const MapType& M, const Point& Fst, const Point& Last) {
static std::array<int, 4> XP = { 0,1,0,-1 };
static std::array<int, 4> YP = { 1,0,-1,0 };
std::uintmax_t MinWeight = PoorSearch(M, Fst, Last);
std::uintmax_t Weight = 0;
FootPrint2 FP;
FootPrint2 R;
FP.push_back({ Fst,0,0,0 });
while(FP.size()){
//for (std::get<1>(FP.back()); std::get<1>(FP.back()) < 4; std::get<1>(FP.back())++) {
auto i = std::get<1>(FP.back())++;
if (i == 3) {
FP.pop_back();
continue;
}
auto& o = FP.back();
auto& P = std::get<0>(o);
Weight = std::get<3>(o);
auto X = std::get<0>(P) + XP[i];
auto Y = std::get<1>(P) + YP[i];
if (X < 0) { continue; }
if (Y < 0) { continue; }
if (X >= M.front().size()) { continue; }
if (Y >= M.size()) { continue; }
auto it = std::find_if(FP.begin(), FP.end(), [&](auto& o) {return (std::get<0>(std::get<0>(o)) == X) && (std::get<1>(std::get<0>(o)) == Y); });
if (it != FP.end()) { continue; }
if (X == std::get<0>(Last) && Y == std::get<1>(Last)) {
if (Weight <= MinWeight) {
FP.push_back({ { X,Y }, i, M[Y][X], Weight + M[Y][X] });
R = FP;
MinWeight = Weight;
}
//FP.pop_back();
continue;
}
else {
if (Weight + M[Y][X] >= MinWeight) {
if(i==3)FP.pop_back();
continue;
}
else {
Weight += M[Y][X];
}
}
FP.push_back({ { X,Y },0, M[Y][X], Weight });
}
return { MinWeight,R };
}
MapType MakeVector() {
MapType M{
{0,2,9,5,3,9,4,1,3 },
{7,1,5,4,6,7,9,8,8 },
{8,3,4,1,1,2,9,4,6 },
{2,3,7,1,6,5,4,2,6 },
{4,7,3,8,5,7,3,6,0 },
};
return M;
}
int main() {
MapType M = MakeVector();
FootPrint FP;
FootPrint2 FP2;
std::uintmax_t R;
//std::tie(R,FP) = SearchPath(M, { 0,0 }, { 8,4 });
std::tie(R,FP2) = SearchPathL(M, { 0,0 }, { 8,4 });
std::cout << R << std::endl;
for (auto& o : FP2) {
//std::cout << std::get<0>(o) << ',' << std::get<1>(o) << ',' << M[std::get<1>(o)][std::get<0>(o)] << std::endl;
std::cout << std::get<0>(std::get<0>(o)) << ',' << std::get<1>(std::get<0>(o)) << ',' << M[std::get<1>(std::get<0>(o))][std::get<0>(std::get<0>(o))] << std::endl;
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8Y3N0ZGludD4KI2luY2x1ZGUgPHR1cGxlPiAKI2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGFycmF5PgoKCnR5cGVkZWYgc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8c3RkOjp1aW50NjRfdD4+IE1hcFR5cGU7CnR5cGVkZWYgc3RkOjp0dXBsZTxzdGQ6OmludDY0X3QsIHN0ZDo6aW50NjRfdD4gUG9pbnQ7CnR5cGVkZWYgc3RkOjp2ZWN0b3I8UG9pbnQ+IEZvb3RQcmludDsKCmludCBQYSA9IDI7CgpzdGQ6OnVpbnRtYXhfdCBQb29yU2VhcmNoKGNvbnN0IE1hcFR5cGUmIE0sIGNvbnN0IFBvaW50JiBGc3QsIGNvbnN0IFBvaW50JiBMYXN0KSB7CgoJc3RkOjp1aW50bWF4X3QgVyA9IDA7CglzdGQ6OmludDY0X3QgaSA9IDA7CglzdGQ6OnNpemVfdCBqID0gMDsKCWZvciAoaj0gc3RkOjpnZXQ8MT4oRnN0KTtqICE9IHN0ZDo6Z2V0PDE+KExhc3QpOyBqICs9IChzdGQ6OmdldDwxPihGc3QpIC0gc3RkOjpnZXQ8MT4oTGFzdCkpID8gMSA6IC0xKSB7CgkJVyArPSBNW2pdW3N0ZDo6Z2V0PDA+KEZzdCldOwoJfQoKCWZvciAoaSA9IHN0ZDo6Z2V0PDA+KEZzdCk7IGkgIT0gc3RkOjpnZXQ8MD4oTGFzdCk7IGkgKz0gKHN0ZDo6Z2V0PDA+KEZzdCkgLSBzdGQ6OmdldDwwPihMYXN0KSkgPyAxIDogLTEpIHsKCQlXICs9IE1bai0xXVtpXTsKCX0KCQoJcmV0dXJuIFc7Cn0KLyoqLwpib29sIFNlYXJjaFBhdGhfcihjb25zdCBNYXBUeXBlJiBNLCBGb290UHJpbnQgRlAsIGNvbnN0IFBvaW50JiBOb3csIGNvbnN0IFBvaW50JiBMYXN0LCBjb25zdCBzdGQ6OnVpbnRtYXhfdCYgV2FpdCwgc3RkOjppbnRtYXhfdCYgTWluLEZvb3RQcmludCYgRlBSKSB7CglzdGF0aWMgc3RkOjphcnJheTxpbnQsIDQ+IFhQID0geyAwLDEsMCwtMSB9OwoJc3RhdGljIHN0ZDo6YXJyYXk8aW50LCA0PiBZUCA9IHsgMSwwLC0xLDAgfTsKCXN0YXRpYyBzdGQ6OnVpbnRtYXhfdCBDID0gMDsKCglhdXRvIFgxID0gc3RkOjpnZXQ8MD4oTm93KTsKCWF1dG8gWTEgPSBzdGQ6OmdldDwxPihOb3cpOwoJYXV0byBYMiA9IHN0ZDo6bWF4PGludD4oc3RkOjpnZXQ8MD4oTGFzdCksIDApOwoJYXV0byBZMiA9IHN0ZDo6bWF4PGludD4oc3RkOjpnZXQ8MT4oTGFzdCksIDApOwoJaWYgKChYMSA9PSBYMikgJiYgKFkxID09IFkyKSkgewoJCWlmIChNaW4gPj0gV2FpdCkgewoJCQlGUC5wdXNoX2JhY2soeyBYMSxZMSB9KTsKCQkJTWluID0gV2FpdDsKCQkJQysrOwkKCQkJRlBSID0gRlA7CgkJfQoJfQoKCWlmIChNaW4gPD0gV2FpdCkgewoJCXJldHVybiBmYWxzZTsKCX0KCUZQLnB1c2hfYmFjayh7IHN0ZDo6Z2V0PDA+KE5vdyksc3RkOjpnZXQ8MT4oTm93KSB9KTsKCWZvciAoc3RkOjpzaXplX3QgaSA9IDA7IGkgPCA0OyBpKyspIHsKCQlpZiAoc3RkOjpnZXQ8MD4oTm93KSArIFhQW2ldIDwgMCkgeyBjb250aW51ZTsgfTsKCQlpZiAoc3RkOjpnZXQ8MT4oTm93KSArIFlQW2ldIDwgMCkgeyBjb250aW51ZTsgfTsKCQlpZiAoc3RkOjpnZXQ8MD4oTm93KSArIFhQW2ldID49IE0uZnJvbnQoKS5zaXplKCkgKSB7IGNvbnRpbnVlOyB9CgkJaWYgKHN0ZDo6Z2V0PDE+KE5vdykgKyBZUFtpXSA+PSBNLnNpemUoKSkgeyBjb250aW51ZTsgfQoJCWF1dG8gaXQgPSBzdGQ6OmZpbmRfaWYoRlAuYmVnaW4oKSwgRlAuZW5kKCksIFsmXShhdXRvJiBvKSB7cmV0dXJuIChzdGQ6OmdldDwwPihvKSA9PSBzdGQ6OmdldDwwPihOb3cpICsgWFBbaV0pICYmIChzdGQ6OmdldDwxPihvKSA9PSBzdGQ6OmdldDwxPihOb3cpICsgWVBbaV0pOyB9KTsKCgkJaWYgKGl0ICE9IEZQLmVuZCgpKSB7IGNvbnRpbnVlOyB9CgoKCQlTZWFyY2hQYXRoX3IoTSwgRlAseyBzdGQ6OmdldDwwPihOb3cpICsgWFBbaV0sc3RkOjpnZXQ8MT4oTm93KSArIFlQW2ldIH0sIExhc3QsIFdhaXQgKyBNW3N0ZDo6Z2V0PDE+KE5vdykgKyBZUFtpXV1bc3RkOjpnZXQ8MD4oTm93KSArIFhQW2ldXSwgTWluLEZQUik7CgkJCgoKCX0KCUZQLnBvcF9iYWNrKCk7CgoJcmV0dXJuIHRydWU7CgoKCn0KCnN0ZDo6dHVwbGU8c3RkOjp1aW50bWF4X3QsRm9vdFByaW50PiBTZWFyY2hQYXRoKGNvbnN0IE1hcFR5cGUmIE0sIGNvbnN0IFBvaW50JiBGc3QsIGNvbnN0IFBvaW50JiBMYXN0KSB7CglzdGQ6OmludG1heF90IE1pbiA9IFBvb3JTZWFyY2goTSwgRnN0LCBMYXN0KTsKCUZvb3RQcmludCBmcDsKCUZvb3RQcmludCBGUFI7CgkvL2ZwLnB1c2hfYmFjayh7IDAsMCB9KTsKCS8vRVNTOjpMb2NhdGUoc3RkOjpnZXQ8MD4oRnN0KStQYSwgc3RkOjpnZXQ8MT4oRnN0KStQYSk7CgkvL3N0ZDo6Y291dCA8PCAnKic7CglTZWFyY2hQYXRoX3IoTSwgZnAsIEZzdCwgTGFzdCwgMCwgTWluLEZQUik7CgoJcmV0dXJuIHsgTWluLEZQUiB9OwoKfQoKdHlwZWRlZiBzdGQ6OnR1cGxlPFBvaW50LCBzdGQ6OmludDY0X3Qsc3RkOjp1aW50bWF4X3Qsc3RkOjp1aW50bWF4X3Q+IEZvb3REYXRhOy8vcG9zLGRpcix3ZWlnaHQsbm93X3dlaWdodAp0eXBlZGVmIHN0ZDo6dmVjdG9yPEZvb3REYXRhPiBGb290UHJpbnQyOwoKc3RkOjp0dXBsZTxzdGQ6OnVpbnRtYXhfdCwgRm9vdFByaW50Mj4gU2VhcmNoUGF0aEwoY29uc3QgTWFwVHlwZSYgTSwgY29uc3QgUG9pbnQmIEZzdCwgY29uc3QgUG9pbnQmIExhc3QpIHsKCXN0YXRpYyBzdGQ6OmFycmF5PGludCwgND4gWFAgPSB7IDAsMSwwLC0xIH07CglzdGF0aWMgc3RkOjphcnJheTxpbnQsIDQ+IFlQID0geyAxLDAsLTEsMCB9OwoJc3RkOjp1aW50bWF4X3QgTWluV2VpZ2h0ID0gUG9vclNlYXJjaChNLCBGc3QsIExhc3QpOwoJc3RkOjp1aW50bWF4X3QgV2VpZ2h0ID0gMDsKCglGb290UHJpbnQyIEZQOwoJRm9vdFByaW50MiBSOwoKCUZQLnB1c2hfYmFjayh7IEZzdCwwLDAsMCB9KTsKCgl3aGlsZShGUC5zaXplKCkpewoJLy9mb3IgKHN0ZDo6Z2V0PDE+KEZQLmJhY2soKSk7IHN0ZDo6Z2V0PDE+KEZQLmJhY2soKSkgPCA0OyBzdGQ6OmdldDwxPihGUC5iYWNrKCkpKyspIHsKCQlhdXRvIGkgPSBzdGQ6OmdldDwxPihGUC5iYWNrKCkpKys7CgkJaWYgKGkgPT0gMykgewoJCQlGUC5wb3BfYmFjaygpOwoJCQljb250aW51ZTsKCQl9CgkJYXV0byYgbyA9IEZQLmJhY2soKTsKCQlhdXRvJiBQID0gc3RkOjpnZXQ8MD4obyk7CgkJV2VpZ2h0ID0gc3RkOjpnZXQ8Mz4obyk7CgoJCWF1dG8gWCA9IHN0ZDo6Z2V0PDA+KFApICsgWFBbaV07CgkJYXV0byBZID0gc3RkOjpnZXQ8MT4oUCkgKyBZUFtpXTsKCgkJaWYgKFggPCAwKSB7IGNvbnRpbnVlOyB9CgkJaWYgKFkgPCAwKSB7IGNvbnRpbnVlOyB9CgkJaWYgKFggPj0gTS5mcm9udCgpLnNpemUoKSkgeyBjb250aW51ZTsgfQoJCWlmIChZID49IE0uc2l6ZSgpKSB7IGNvbnRpbnVlOyB9CgoJCWF1dG8gaXQgPSBzdGQ6OmZpbmRfaWYoRlAuYmVnaW4oKSwgRlAuZW5kKCksIFsmXShhdXRvJiBvKSB7cmV0dXJuIChzdGQ6OmdldDwwPihzdGQ6OmdldDwwPihvKSkgPT0gWCkgJiYgKHN0ZDo6Z2V0PDE+KHN0ZDo6Z2V0PDA+KG8pKSA9PSBZKTsgfSk7CgkJaWYgKGl0ICE9IEZQLmVuZCgpKSB7IGNvbnRpbnVlOyB9CgoKCQlpZiAoWCA9PSBzdGQ6OmdldDwwPihMYXN0KSAmJiBZID09IHN0ZDo6Z2V0PDE+KExhc3QpKSB7CgkJCWlmIChXZWlnaHQgPD0gTWluV2VpZ2h0KSB7CgkJCQlGUC5wdXNoX2JhY2soeyB7IFgsWSB9LCBpLCBNW1ldW1hdLCBXZWlnaHQgKyBNW1ldW1hdIH0pOwoJCQkJUiA9IEZQOwoJCQkJTWluV2VpZ2h0ID0gV2VpZ2h0OwoKCQkJfQoJCQkvL0ZQLnBvcF9iYWNrKCk7CgkJCWNvbnRpbnVlOwoJCX0KCQllbHNlIHsKCgkJCWlmIChXZWlnaHQgKyBNW1ldW1hdID49IE1pbldlaWdodCkgewoJCQkJaWYoaT09MylGUC5wb3BfYmFjaygpOwoJCQkJY29udGludWU7CgkJCX0KCQkJZWxzZSB7CgkJCQlXZWlnaHQgKz0gTVtZXVtYXTsKCQkJfQoJCX0KCQlGUC5wdXNoX2JhY2soeyB7IFgsWSB9LDAsIE1bWV1bWF0sIFdlaWdodCB9KTsKCX0KCglyZXR1cm4geyBNaW5XZWlnaHQsUiB9Owp9CgpNYXBUeXBlIE1ha2VWZWN0b3IoKSB7CglNYXBUeXBlIE17CgkJezAsMiw5LDUsMyw5LDQsMSwzIH0sCgkJezcsMSw1LDQsNiw3LDksOCw4IH0sCgkJezgsMyw0LDEsMSwyLDksNCw2IH0sCgkJezIsMyw3LDEsNiw1LDQsMiw2IH0sCgkJezQsNywzLDgsNSw3LDMsNiwwIH0sCgl9OwoKCXJldHVybiBNOwp9CgppbnQgbWFpbigpIHsKCU1hcFR5cGUgTSA9IE1ha2VWZWN0b3IoKTsKCUZvb3RQcmludCBGUDsKCUZvb3RQcmludDIgRlAyOwoJc3RkOjp1aW50bWF4X3QgUjsKCgkvL3N0ZDo6dGllKFIsRlApID0gU2VhcmNoUGF0aChNLCB7IDAsMCB9LCB7IDgsNCB9KTsKCXN0ZDo6dGllKFIsRlAyKSA9IFNlYXJjaFBhdGhMKE0sIHsgMCwwIH0sIHsgOCw0IH0pOwoKCXN0ZDo6Y291dCA8PCBSIDw8IHN0ZDo6ZW5kbDsKCglmb3IgKGF1dG8mIG8gOiBGUDIpIHsKCQkvL3N0ZDo6Y291dCA8PCBzdGQ6OmdldDwwPihvKSA8PCAnLCcgPDwgc3RkOjpnZXQ8MT4obykgPDwgJywnIDw8IE1bc3RkOjpnZXQ8MT4obyldW3N0ZDo6Z2V0PDA+KG8pXSA8PCBzdGQ6OmVuZGw7CgkJc3RkOjpjb3V0IDw8IHN0ZDo6Z2V0PDA+KHN0ZDo6Z2V0PDA+KG8pKSA8PCAnLCcgPDwgc3RkOjpnZXQ8MT4oc3RkOjpnZXQ8MD4obykpIDw8ICcsJyA8PCBNW3N0ZDo6Z2V0PDE+KHN0ZDo6Z2V0PDA+KG8pKV1bc3RkOjpnZXQ8MD4oc3RkOjpnZXQ8MD4obykpXSA8PCBzdGQ6OmVuZGw7Cgl9CgoJcmV0dXJuIDA7Cn0=