NC24036. [USACO 2016 Jan P]Lights Out
描述
输入描述
The first line of the input contains N (4≤N≤200). Each of the next N lines contains two integers, describing the points (xi,yi) in clockwise order around the barn. These integers are in the range −100,000…100,000.
输出描述
Please output the smallest possible worst-case amount by which Bessie's optimal distance in the dark is longer than her optimal distance in a lit barn, where the worst case is taken over all possible vertices at which Bessie can start.
示例1
输入:
4 0 0 0 10 1 10 1 0
输出:
2
说明:
In this example, Bessie can feel that she is initially standing at an inward bend, however since in this example all corners are inward bends this tells her little information.Python3(3.9) 解法, 执行用时: 740ms, 内存消耗: 3320K, 提交时间: 2020-12-21 19:23:30
N = int(input()) vertices = [] dists = [] prev = None for _ in range(N): s, t = tuple(map(int, input().split())) if vertices: dists.append(abs(vertices[-1][0] - s) + abs(vertices[-1][1] - t)) vertices.append((s, t)) # dist between last vertex and first dists.append(abs(vertices[0][0] - vertices[-1][0]) + \ abs(vertices[0][1] - vertices[-1][1])) angles = [] # records the angle at the vertex for i in range(N): prev, cur, nxt = vertices[i - 1], vertices[i], vertices[(i + 1) % N] if prev[1] == cur[1] and prev[0] > cur[0] and cur[0] == nxt[0] and cur[1] < nxt[1]: angles.append(1) elif prev[0] == cur[0] and prev[1] < cur[1] and cur[1] == nxt[1] and cur[0] < nxt[0]: angles.append(1) elif prev[1] == cur[1] and prev[0] < cur[0] and cur[0] == nxt[0] and cur[1] > nxt[1]: angles.append(1) elif prev[0] == cur[0] and prev[1] > cur[1] and cur[1] == nxt[1] and cur[0] > nxt[0]: angles.append(1) else: angles.append(-1) def main(): indices = range(1, N) possibilities = {} max_cost = 0 for i in indices: knowledge = angles[i] if knowledge in possibilities: possibilities[knowledge].append(i) else: possibilities[knowledge] = [i] for _, indices in possibilities.items(): if len(indices) == 1: continue else: max_cost = max(max_cost, left_right_search(indices)) print(max_cost) def find_cost(index, shift): optimal_dist = min(sum(dists[index:]), sum(dists[:index])) optimal_dist_for_shifted_index = min(sum(dists[index+shift:]), sum(dists[:index+shift])) return optimal_dist_for_shifted_index - optimal_dist def left_right_search(indices, shift=0): max_left_cost = left_search(indices, shift=shift) max_right_cost = right_search(indices, shift=shift) return min(max_left_cost, max_right_cost) def left_search(indices, shift): #left is anti-clockwise LOL n = len(indices) possibilities = {} shift -= 1 max_cost = -1e9 for i in indices: if i + shift == 0: continue knowledge = angles[i+shift] * dists[i+shift] if knowledge in possibilities: possibilities[knowledge].append(i) else: possibilities[knowledge] = [i] for knowledge, indices in possibilities.items(): if len(indices) == 1: max_cost = max(max_cost, abs(knowledge) + find_cost(indices[0], shift)) elif len(indices) == n: max_cost = max(max_cost, abs(knowledge) + left_search(indices, shift)) else: max_cost = max(max_cost, abs(knowledge) + left_right_search(indices, shift)) return max_cost def right_search(indices, shift): #left is anti-clockwise LOL n = len(indices) possibilities = {} shift += 1 max_cost = -1e9 for i in indices: if i + shift == N: continue knowledge = angles[i+shift] * dists[i+shift-1] if knowledge in possibilities: possibilities[knowledge].append(i) else: possibilities[knowledge] = [i] for knowledge, indices in possibilities.items(): if len(indices) == 1: max_cost = max(max_cost, abs(knowledge) + find_cost(indices[0], shift)) elif len(indices) == n: max_cost = max(max_cost, abs(knowledge) + right_search(indices, shift)) else: max_cost = max(max_cost, abs(knowledge) + left_right_search(indices, shift)) return max_cost main()
C++(clang++11) 解法, 执行用时: 42ms, 内存消耗: 37296K, 提交时间: 2020-12-20 12:50:22
#include <iostream> #include <vector> #include <algorithm> using namespace std; #define MAXN 210 #define INF 0x3FFFFFFF int opt[MAXN]; int psum[MAXN]; int canon[MAXN*2][MAXN*2]; vector<int> lparents[MAXN][MAXN]; vector<int> rparents[MAXN][MAXN]; int dp[MAXN][MAXN][MAXN][2]; int main() { int N; cin >> N; vector<pair<long long, long long> > A(N); for (int i = 0; i < N; i++) { cin >> A[i].first >> A[i].second; } vector<int> S(1, 0); for (int i = 0; i < N; i++) { int j = (i + 1) % N; int k = (i + 2) % N; S.push_back(abs(A[i].first - A[j].first) +abs(A[i].second - A[j].second)); if ((A[i].first - A[j].first) * (A[k].second - A[j].second) - (A[k].first - A[j].first) * (A[i].second - A[j].second) > 0) { S.push_back(-1); } else { S.push_back(-2); } } S.back() = 0; for (int i = 0; i < N; i++) { psum[i + 1] = opt[i + 1] = opt[i] + S[2 * i + 1]; } opt[N] = 0; for (int i = N - 1; i >= 0; i--) { opt[i] = min(opt[i], opt[i + 1] + S[2 * i + 1]); } for (int ln = 1; ln <= S.size(); ln++) { for (int i = 0; i + ln <= S.size(); i++) { for (int& j = canon[i][ln]; j < i; j++) { if (canon[j][ln - 1] == canon[i][ln - 1] && S[j + ln - 1] == S[i + ln - 1]) { break; } } } } for (int i = 0; i < S.size(); i += 2) { for (int ln = 3; i + ln <= S.size(); ln += 2) { if (i != canon[i][ln]) { continue; } lparents[canon[i + 2][ln - 2] / 2][ln / 2].push_back(i / 2); rparents[canon[i][ln - 2] / 2][ln / 2].push_back(i / 2); } } int result = 0; for (int ln = N; ln >= 1; ln--) { for (int i = 0; i + ln <= N + 1; i++) { if (canon[2 * i][2 * ln - 1] != 2 * i) { continue; } int dist_across = psum[i + ln - 1] - psum[i]; for (int strt = 0; strt < ln; strt++) { for (int side = 0; side < 2; side++) { if (i == 0 || i + ln == N + 1) { dp[i][ln][strt][side] = -opt[i + strt]; continue; } int lft_cst = -INF; vector<int>::iterator it; for(it=lparents[i][ln].begin(); it!=lparents[i][ln].end(); it++) { lft_cst = max(lft_cst, S[2 * (*it) + 1] + dp[(*it)][ln + 1][strt + 1][0]); } int rht_cst = -INF; for(it= rparents[i][ln].begin(); it!=rparents[i][ln].end(); it++) { rht_cst = max(rht_cst,S[2 * ((*it) + ln) - 1] + dp[(*it)][ln + 1][strt][1]); } (side ? lft_cst : rht_cst) += dist_across; dp[i][ln][strt][side] = min(lft_cst, rht_cst); if (ln == 1) { result = max(result, dp[i][ln][strt][side]); } } } } } cout << result << endl; return 0; }