#include #include #include #include #include #include #include #include using namespace std; #define mp(first, second) make_pair(first, second) typedef unsigned long long ul; typedef long long ll; typedef pair ii; typedef vector vii; typedef vector vi; vector numbers; vector initialNums; vector> positionsCosts; vector> valuesCosts; vector ans; vector> swaps; vector>> graph; vector visited; vector dist; vector previous; string toString(int num) { stringstream ss; ss << num; return ss.str(); } void selectionSort() { vector swapsList; ans.push_back(0); for (int i = 0; i < numbers.size(); i++) { int bestIdx = i; for (int j = i + 1; j < numbers.size(); j++) { if (numbers[j] < numbers[bestIdx]) { bestIdx = j; } } swap(numbers[i], numbers[bestIdx]); ans[0] += positionsCosts[i][bestIdx]; ans[0] += valuesCosts[numbers[i] - 1][numbers[bestIdx] - 1]; string currSwap = toString(i + 1) + " " + toString(bestIdx + 1); swapsList.push_back(currSwap); } swaps.push_back(swapsList); } void bringBackToInitial() { for (int i = 0; i < numbers.size(); i++) { numbers[i] = initialNums[i]; } } void sortValToPos() { vector swapsList; ans.push_back(0); for (int i = 0; i < numbers.size(); i++) { if (numbers[i] != i + 1) { int toIdx = numbers[i] - 1; swap(numbers[i], numbers[toIdx]); ans[1] += positionsCosts[i][toIdx]; ans[1] += valuesCosts[numbers[i] - 1][numbers[toIdx] - 1]; string currSwap = toString(i + 1) + " " + toString(toIdx + 1); swapsList.push_back(currSwap); i--; } } swaps.push_back(swapsList); } void initGraph() { graph.clear(); graph.resize(numbers.size()); for (int i = 0; i < numbers.size(); i++) { for (int j = 0; j < numbers.size(); j++) { if (i != j) { int positionCost = positionsCosts[i][j]; //int valueCost = valuesCosts[numbers[i] - 1][numbers[j] - 1]; graph[i].push_back(mp(positionCost, j)); } } } visited.assign(numbers.size(), false); dist.assign(numbers.size(), 2000000007); previous.assign(numbers.size(), -1); } void dijkstra(int start) { priority_queue> q; q.push(mp(0, start)); dist[start] = 0; while (!q.empty()) { ii currPair = q.top(); q.pop(); int u = currPair.second; int currDist = currPair.first; if (!visited[u]) { visited[u] = true; for (int i = 0; i < graph[u].size(); i++) { ii neighbour = graph[u][i]; int v = neighbour.second; int neighbourEdge = neighbour.first; if (numbers[v] != v + 1) { int neighbourDist = dist[v]; int valueCost = valuesCosts[numbers[u] - 1][numbers[v] - 1]; if (currDist + neighbourEdge + valueCost < neighbourDist) { dist[v] = currDist + neighbourEdge + valueCost; q.push(mp(currDist + neighbourEdge + valueCost, v)); previous[v] = u; } } } } } } int main() { ifstream iStream("sorting.in"); ofstream oStream("sorting.out"); int n; iStream >> n; for (int i = 0; i < n; i++) { int currNum; iStream >> currNum; numbers.push_back(currNum); initialNums.push_back(currNum); } positionsCosts.resize(n); int posType; iStream >> posType; for (int i = 0; i < n; i++) { int currNum; for (int j = 0; j < n; j++) { iStream >> currNum; positionsCosts[i].push_back(currNum); } } valuesCosts.resize(n); int valType; iStream >> valType; for (int i = 0; i < n; i++) { int currNum; for (int j = 0; j < n; j++) { iStream >> currNum; valuesCosts[i].push_back(currNum); } } selectionSort(); bringBackToInitial(); sortValToPos(); bringBackToInitial(); initGraph(); int dijkstraCost = 0; vector dijkstraSwaps; bool isSorted = true; for (int i = 0; i < numbers.size(); i++) { int currNum = numbers[i]; if (currNum != i + 1) { dijkstra(i); dijkstraCost += 0; int retrace = currNum - 1; while (previous[retrace] != -1) { swap(numbers[i], numbers[retrace]); string currSwap = toString(i + 1) + " " + toString(retrace + 1); dijkstraCost += positionsCosts[i][retrace]; dijkstraCost += valuesCosts[numbers[i] - 1][numbers[retrace] - 1]; dijkstraSwaps.push_back(currSwap); retrace = previous[retrace]; } initGraph(); i--; } } for (int i = 0; i < numbers.size() - 1; i++) { if (numbers[i] >= numbers[i + 1]) { isSorted = false; break; } } if (isSorted) { swaps.push_back(dijkstraSwaps); ans.push_back(dijkstraCost); } int bestIdx = -1; int bestCost = 2000000007; for (int i = 0; i < ans.size(); i++) { int currCost = ans[i]; if (currCost < bestCost) { bestCost = currCost; bestIdx = i; } } oStream << swaps[bestIdx].size() << '\n'; for (int i = 0; i < swaps[bestIdx].size(); i++) { oStream << swaps[bestIdx][i] << '\n'; } return 0; }