NC24027. [USACO 2016 Jan G]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.
输出描述
Output the largest amount that Bessie's travel distance will increase in the worst case starting position using the strategy in the problem statement.
示例1
输入:
4 0 0 0 10 1 10 1 0
输出:
2
说明:
In this example, Bessie can feel that she is initially standing at a 90-degree angle, but she cannot tell if she is initially standing at vertex 2, 3, or 4. After taking a step along one edge in the clockwise direction, Bessie either reaches the exit or can uniquely determine her location based on the length of this edge. The distances she obtains are:Python3(3.9) 解法, 执行用时: 54ms, 内存消耗: 3052K, 提交时间: 2020-12-20 23:49: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(90) elif prev[0] == cur[0] and prev[1] < cur[1] and cur[1] == nxt[1] and cur[0] < nxt[0]: angles.append(90) elif prev[1] == cur[1] and prev[0] < cur[0] and cur[0] == nxt[0] and cur[1] > nxt[1]: angles.append(90) elif prev[0] == cur[0] and prev[1] > cur[1] and cur[1] == nxt[1] and cur[0] > nxt[0]: angles.append(90) else: angles.append(270) # find other starting angles with same value def find_others(start_index): res = [] a = angles[start_index] for i in range(1, N): if (i + start_index != N) and angles[(i + start_index) % N] == a: res.append((i + start_index) % N) return res # find the result corresponding to a start_index def simulate(start_index): optimal_dist = min(sum(dists[start_index:]), sum(dists[:start_index])) indices = find_others((start_index)) # feel the first angle total_dist = 0 inc = 0 while indices: total_dist += dists[start_index + inc] inc += 1 if start_index + inc == N: return total_dist - optimal_dist indices = [i for i in indices if i + inc != N and dists[(i + inc - 1) % N] == dists[(start_index + inc - 1) % N] \ and angles[(i + inc) % N] == angles[(start_index + inc) % N]] total_dist += min(sum(dists[(start_index + inc) % N:]), sum(dists[:(start_index + inc) % N])) return total_dist - optimal_dist res = 0 for i in range(1, N): res = max(res, simulate(i)) print(res)
C++(clang++11) 解法, 执行用时: 38ms, 内存消耗: 12328K, 提交时间: 2020-12-19 21:17:48
#include <bits/stdc++.h> #define rgi int #define ll long long using namespace std; inline int read() { int f=1,x=0;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f; } struct node{ int x,y; }p[205]; int n,f[205]; void Cir(int &x){ if(x==n+1) x=1; if(x==n+2) x=2; if(x==0) x=n; } inline int CrossProduct(int x1,int y1,int x2,int y2){ return x1*y2-x2*y1; } inline int dist(int i,int j){ return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y); } int main() { ios::sync_with_stdio(0);cin.tie(0); vector<int> S; S.push_back(0); n=read(); for(rgi i=1;i<=n;++i){ p[i].x=read(); p[i].y=read(); } for(rgi i=1;i<=n;++i){ int j=i+1,k=i+2; Cir(j); Cir(k); S.push_back(dist(i,j)); if(CrossProduct(p[j].x-p[i].x,p[j].y-p[i].y,p[k].x-p[j].x,p[k].y-p[j].y)>0) S.push_back(-1); else S.push_back(-2); } S.back()=0; for(rgi i=2;i<=n;++i){ int j=i+1; Cir(j); int tmp1=dist(i,j); while(j!=1){ int jj=j; j++; Cir(j); tmp1+=dist(jj,j); } j=i-1; Cir(j); int tmp2=dist(i,j); while(j!=1){ int jj=j; j--; Cir(j); tmp2+=dist(jj,j); } f[i]=min(tmp1,tmp2); } multiset<vector<int> > Set; for(rgi i=0;i<(int)S.size();i+=2){ for(rgi j=1;i+j<=(int)S.size();j+=2){ Set.insert(vector<int>(S.begin()+i,S.begin()+i+j)); } } int ans=0; for(rgi i=2;i<=n;++i){ int j,cost=0; for(j=1;;j+=2){ if(Set.count(vector<int>(S.begin()+(i-1)*2,S.begin()+(i-1)*2+j))==1) break; cost+=S[(i-1)*2+j]; } ans=max(ans,cost+f[i+j/2]-f[i]); } cout<<ans<<endl; return 0; }