1. 程式人生 > >「 Luogu P3137 」X 「 USACO16FEB 」 圓形谷倉

「 Luogu P3137 」X 「 USACO16FEB 」 圓形谷倉

序列 %d als tor priority int cstring true 移動

# 題目大意

管理大大給修下 $\text{Markdown}$ 吧,嚴重影響做題體驗啊。

這道題的意思很簡單就是給你一個長度是 $n$ 的環,這個環上不均勻的分布著 $n$ 頭奶牛。一頭奶牛移動要花費的代價是距離的平方,現在讓你求出使得每個點上都有一頭奶牛需要花費的最小代價,註意,奶牛只能順時針移動。

# 解題思路

首先斷環成鏈這個大家應該都知道,就是將原序列 copy 一份放到後面去。

然後考慮如果一頭奶牛在移動的過程中沒有經過其他奶牛,那這一定是最優的方案。還有就是如果一個點有奶牛,那將奶牛運到它順時針防線上離它連續一段 $0$ 的最後一個 $0$。

枚舉初始位置,從初始位置開始如果遇到有牛的地方,就將這個位置放到優先隊列 (小根堆) 裏,在往後掃的過程中將其慢慢移動過來。

直觀的說就是下面這個式子:

$$a^2+b^2<(a+b)^2$$

# 附上代碼

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int n, a[2003], cnt, ans = 1e9;
priority_queue <int, vector<int>, greater<int> > Q;
bool flag = true; int main() { scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); a[i+n] = a[i]; } static int tmp; for(int i=1; i<=n; i++) { cnt = 0, flag = true; for(int j=i; j<=i+n-1; j++) { if(Q.empty() && a[j] == 0
) {flag = false; break;} tmp = a[j]; while (tmp--) Q.push(j); tmp = Q.top(), Q.pop(); cnt += (tmp-j) * (tmp-j); } if(!flag) continue; ans = min(ans, cnt); } printf("%d", ans); }

「 Luogu P3137 」X 「 USACO16FEB 」 圓形谷倉