int shortestDistance(int xMe, int yMe, int xHome, int yHome, vector <string> teleports) { #if 1 PVec points; points.push_back(P(xMe, yMe)); points.push_back(P(xHome, yHome)); PPMap warp; int i; for (i = 0; i < (int)teleports.size(); ++i) { istringstream s(teleports[i]); P p1, p2; s >> p1.first >> p1.second >> p2.first >> p2.second; points.push_back(p1); points.push_back(p2); warp[p1] = p2; warp[p2] = p1; } LLV Done(points.size()); PLLMap Costs; LL total = 0; int min_index = 0; while (min_index != 1) { Done[min_index] = 1; P Last = points[min_index]; LL min_cost = INF; for (i = 1; i < (int)points.size(); ++i) { if (Done[i]) { continue; } LL prev = Costs[points[i]]; LL d = Distance(Last, points[i]); PPMap::const_iterator it = warp.find(points[i]); if (it != warp.end()) { LL w = 10 + Distance(Last, it->second); d = min(d, w); } LL cost = total + d; if (!prev || cost < prev) { Costs[points[i]] = cost; } else { cost = prev; } if (cost < min_cost) { min_index = i; min_cost = cost; } } total = min_cost; } return (int)total; #else P Me(xMe, yMe); P Home(xHome, yHome); PVec pv1, pv2; LLV GoalCost; int i, j; for (i = 0; i < (int)teleports.size(); ++i) { int x1, y1, x2, y2; if (sscanf(teleports[i].c_str(), "%d %d %d %d", &x1, &y1, &x2, &y2) != 4) { return -1; } pv1.push_back(P(x1, y1)); pv2.push_back(P(x2, y2)); // teleport + walk to goal GoalCost.push_back(10 + Distance(*pv2.rbegin(), Home)); pv1.push_back(P(x2, y2)); pv2.push_back(P(x1, y1)); GoalCost.push_back(10 + Distance(*pv2.rbegin(), Home)); } bool f = true; while (f) { f = false; for (i = 0; i < (int)pv1.size(); ++i) { for (j = 0; j < (int)pv1.size(); ++j) { if (i == j) { continue; } // teleport + walk to anther spot + teleport LL cost = 10 + Distance(pv2[i], pv1[j]) + GoalCost[j]; if (cost < GoalCost[i]) { f = true; GoalCost[i] = cost; } } } } LL Min = Distance(Me, Home); for (i = 0; i < (int)pv1.size(); ++i) { Min = min(Min, Distance(Me, pv1[i]) + GoalCost[i]); } return (int)Min; #endif }
int main() { using jlt::operator<<; using std::cout; using std::cerr; using std::endl; using std::setw; typedef jlt::mathmatrix<int> Mat; typedef std::vector<int> Vec; typedef jlt::polynomial<int> Poly; typedef std::vector<Poly> PVec; typedef std::vector<Mat> MVec; typedef long long int llint; #if 1 std::ifstream indata; indata.open("polycoeffs_n=7.m"); const int n = 7; PVec pl; // Read in Mathematica file of polynomials. skipstring(indata, "(* Created by Wolfram Mathematica ??? : www.wolfram.com *)"); skipstring(indata,"{"); do { skipstring(indata,"{"); Poly p; for (int i = n; i >= 0; --i) { indata >> p[i]; if (i > 0) skipstring(indata,","); } skipstring(indata,"}"); pl.push_back(p); } while (skipstring(indata,",")); Poly p = pl[0]; #else const int n = 4; Poly p; p[0] = 1; p[n] = 1; p[n/2] = -1; p[n/2+1] = -1; p[n/2-1] = -1; #endif int tr = -p[n-1]; cerr << "Checking polynomial " << p; double lambdamax = findroot(p,2.0,1e-8); cerr << " with root " << lambdamax << endl; // Create lower-triangle of matrices. MVec Alow; // Vector of positions of the "1" entry. // 0 <= al[k] <= k+1. al[k]=k+1 corresponds to no 1 at all. Vec al(n), almax(n); for (int k = 0; k < n; ++k) almax[k] = k+1; do { Mat A(n,n); int trA = 0; for (int k = 0; k < n; ++k) { if (al[k] < k+1) A(k,al[k]) = 1; if (al[k] == k) ++trA; } if (trA == tr) Alow.push_back(A); } while(increment_vector(al,almax)); cerr << Alow.size() << " lower-triangular forms\n"; int todo = Alow.size(); // // Upper-triangle of matrices: find valid patterns // int Nup = (n*(n-1))/2; Vec aup(Nup), aupmax(Nup); for (int k = 0; k < Nup; ++k) { aupmax[k] = 1; } // Make index pair for eack k. Vec rowidx(Nup), colidx(Nup); { int row = 0, col = 1; for (int k = 0; k < Nup; ++k) { rowidx[k] = row; colidx[k] = col++; if (col == n) { ++row; col = row+1; } } } llint N = 0; llint validpatterns = 0; llint reduciblepatterns = 0; llint rootexceeded = 0; cout << "{\n"; bool thefirst = true; for (int li = 0; li < (int)todo; ++li) { cerr << "Lower-triangular form " << setw(4) << li+1 << ": "; // Vector of allowable patterns. std::vector<Vec> pattern; int n1min = -1, n1max = -1; do { // Form matrix. Mat A(Alow[li]); for (int k = 0; k < Nup; ++k) A(rowidx[k],colidx[k]) = aup[k]; ++N; if (spectral_radius(A) <= lambdamax) { if (!A.isReducible()) { ++validpatterns; pattern.push_back(aup); int n1 = std::count(aup.begin(),aup.end(),1); if (n1 < n1min || n1min == -1) n1min = n1; if (n1 > n1max || n1max == -1) n1max = n1; } else { ++reduciblepatterns; } } else { ++rootexceeded; } } while(increment_vector(aup,aupmax)); cerr << setw(5) << pattern.size() << " valid patterns"; // Skip lower-triangular forms with no allowable patterns. if (pattern.empty()) { cerr << endl; continue; } cerr << " (size "; int Alownorm = matrix_norm(Alow[li]); cerr << setw(2) << n1min+Alownorm << " to "; cerr << setw(2) << n1max+Alownorm << ")\n"; for (int pa = 0; pa < (int)pattern.size(); ++pa) { // How many 1's in this pattern? int Npat = std::count(pattern[pa].begin(),pattern[pa].end(),1); // Make index pair for eack k. Vec patrowidx(Npat), patcolidx(Npat); { int row = 0, col = 1, m = 0; for (int k = 0; k < (n*(n-1))/2; ++k) { if (pattern[pa][k] == 1) { patrowidx[m] = row; patcolidx[m] = col; ++m; } if (++col == n) { ++row; col = row+1; } } } // Form matrix. // Start with the pattern equal to all ones. Mat A(Alow[li]); for (int k = 0; k < Npat; ++k) A(patrowidx[k],patcolidx[k]) = 1; // Now loop over vales of the entries of the pattern do { ++N; // Compute characteristic polynomial. Poly cpoly(A.charpoly()); if (cpoly == p) { cerr << "Got it!\n"; if (!thefirst) cout << "," << endl; else thefirst = false; A.printMathematicaForm(cout); } } while(increment_upper_triangle(A,patrowidx,patcolidx,lambdamax)); } } cout << "\n}\n"; cerr << validpatterns << endl; cerr << reduciblepatterns << endl; cerr << rootexceeded << endl; cerr << N << endl; }