公式

E - 配送ルートの最適化 / Optimization of Delivery Routes 解説 by admin

DeepSeek V3

Overview

This is a variant of the Traveling Salesman Problem (TSP), where we need to find the minimum cost of a route that visits all locations and returns to the starting location. However, the cost is defined as the square of the Euclidean distance.

Analysis

This problem is known as the Traveling Salesman Problem, which is NP-hard. Since the number of locations \(N\) is at most 16, a brute-force approach would be \(O(N!)\), which is computationally infeasible. Instead, we solve it efficiently using dynamic programming. By representing the set of visited locations using a bitmask and recording the optimal solutions of subproblems, we can find the solution efficiently.

Algorithm

We use bitmask DP (dynamic programming). The state is defined as a pair of “the set of visited locations (bitmask)” and “the current location,” and we record the minimum cost for each state.

Specifically: - dp[mask][i]: the minimum cost when the set of visited locations is mask and the current location is i - Initial state: dp[1][0] = 0 (only location 0 has been visited) - Transition: from each state, move to an unvisited location j, adding the cost to update the DP - Finally, after all locations have been visited (mask = (1<<n)-1), add the cost of returning to location 0 and find the minimum value

Complexity

  • Time complexity: \(O(2^N \times N^2)\)
  • Space complexity: \(O(2^N \times N)\)

When \(N=16\), the number of states is \(2^{16} \times 16 = 1,048,576\), which is a manageable size.

Implementation Notes

  • Use bit operations for efficient state management

  • Initialize with a large value (INF = 10**18)

  • Correctly handle the constraint of starting from location 0 and returning to location 0

  • Note that the cost is the square of the Euclidean distance

  • At the end, after visiting all locations, separately add the return cost to location 0 and find the minimum value

    Source Code

def main():
    import sys
    data = sys.stdin.read().splitlines()
    n = int(data[0])
    points = []
    for i in range(1, n+1):
        x, y = map(int, data[i].split())
        points.append((x, y))
    
    INF = 10**18
    total_mask = (1 << n) - 1
    dp = [[INF] * n for _ in range(1 << n)]
    dp[1][0] = 0
    
    for mask in range(1 << n):
        for i in range(n):
            if dp[mask][i] == INF:
                continue
            for j in range(n):
                if mask & (1 << j):
                    continue
                new_mask = mask | (1 << j)
                cost = (points[i][0] - points[j][0])**2 + (points[i][1] - points[j][1])**2
                if dp[new_mask][j] > dp[mask][i] + cost:
                    dp[new_mask][j] = dp[mask][i] + cost
    
    ans = INF
    for i in range(1, n):
        cost = (points[i][0] - points[0][0])**2 + (points[i][1] - points[0][1])**2
        ans = min(ans, dp[total_mask][i] + cost)
    
    print(ans)

if __name__ == "__main__":
    main()

This editorial was generated by deepseekv3.

投稿日時:
最終更新: