1. 程式人生 > 實用技巧 >Educational Codeforces Round 99 (Rated for Div. 2) E - Four Points

Educational Codeforces Round 99 (Rated for Div. 2) E - Four Points

https://codeforces.com/contest/1455/problem/E

題意:T組,每組給4個點(可上下左右移動),找到一個正方形,使得這四個點到該正方形四個頂點的步數最小。

題解:思維題,隱藏條件是最優解情況下正方形邊長必為兩個點的橫縱標或縱座標之差,在草稿紙上畫出幾種極端情況可簡易證明。

因為最終四個點要組成的是一個正方形,所以固定住左下角的點,用左上角點的縱座標-邊長,右上角點的橫縱座標-邊長,右下角點的橫座標-邊長,此時相當於四個頂點的終點都是一個點(注意不一定是移動到左下角點為最優),對四個點的橫縱座標分別排序,然後依次減去第二大或者第三大的數求和得到每種情況的步數(共有12*24種情況)。

之後就是暴力列舉正方形邊長和四個點全排列的位置,複雜度是12*24*4,t是1e4,複雜度是夠的,實現起來也沒什麼難度,主要還是隱藏條件難發現,不知道為什麼過了三天這道題還是隻有不到200的人補了。

#include<bits/stdc++.h>
#include<vector>
#include<map>
#include<queue>
#define LL long long
#define inf 0x3f3f3f3f
#define MOD 1000000007
#define stree SegTree[root]
#define lson SegTree[root << 1]
#define
rson SegTree[root << 1 | 1] using namespace std; const LL INF = 0x3f3f3f3f3f3f3f3f; const int N = 100005; struct node { LL x, y; }a[20]; LL xx[10], yy[10], p[10], d[20]; int main() { LL T, n, x; cin>>T; for(LL i = 1;i <= 4;i++) p[i] = i; while(T--) { LL cnt = 0, ans = INF;
for(LL i = 1;i <= 4;i++) { scanf("%d%d", &a[i].x, &a[i].y); for(LL j = 1;j < i;j++) { d[++cnt] = abs(a[i].x-a[j].x); d[++cnt] = abs(a[i].y-a[j].y); } } do { for(LL i = 1;i <= cnt;i++) { LL tem = 0; for(LL j = 1;j <= 4;j++) { xx[j] = a[p[j]].x; yy[j] = a[p[j]].y; } yy[2]-=d[i]; xx[3]-=d[i], yy[3]-=d[i]; xx[4]-=d[i]; sort(xx+1, xx+5); sort(yy+1, yy+5); for(LL i = 1;i <= 4;i++) { tem += abs(xx[i]-xx[3]) + abs(yy[i]-yy[3]); } ans = min(ans, tem); //prLLf("ans = %d\n", ans); } }while(next_permutation(p+1, p+5)); printf("%lld\n", ans); } return 0; }