[BZOJ1697][Usaco2007 Feb]Cow Sorting牛排序
阿新 • • 發佈:2017-09-19
style esp 兩種 sta 移動 pri fread 最短 ble
2
3
1
輸入解釋:
隊列裏有三頭牛,脾氣分別為 2,3, 1。
輸出解釋:
2 3 1 : 初始序列
2 1 3 : 交換脾氣為3和1的牛(時間=1+3=4).
1 2 3 : 交換脾氣為1和2的牛(時間=2+1=3). 排個序找出每頭牛應該排到的位置,然後可以發現交換的牛一定是屬於同一個置換循環裏,那麽對於每個循環單獨考慮 有兩種方法搞 第一是每個元素和最小的一直換
第二種是把外面的最小的換進來再不停換,最後換回來
兩種取個最小值就行了
1697: [Usaco2007 Feb]Cow Sorting牛排序
Time Limit: 5 Sec Memory Limit: 64 MB Submit: 712 Solved: 416 [Submit][Status][Discuss]Description
農夫JOHN準備把他的 N(1 <= N <= 10,000)頭牛排隊以便於行動。因為脾氣大的牛有可能會搗亂,JOHN想把牛按脾氣的大小排序。每一頭牛的脾氣都是一個在1到100,000之間的整數並且沒有兩頭牛的脾氣值相同。在排序過程中,JOHN 可以交換任意兩頭牛的位置。因為脾氣大的牛不好移動,JOHN需要X+Y秒來交換脾氣值為X和Y的兩頭牛。 請幫JOHN計算把所有牛排好序的最短時間。
Input
第1行: 一個數, N。
第2~N+1行: 每行一個數,第i+1行是第i頭牛的脾氣值。
Output
第1行: 一個數,把所有牛排好序的最短時間。
Sample Input
32
3
1
輸入解釋:
隊列裏有三頭牛,脾氣分別為 2,3, 1。
Sample Output
7輸出解釋:
2 3 1 : 初始序列
2 1 3 : 交換脾氣為3和1的牛(時間=1+3=4).
1 2 3 : 交換脾氣為1和2的牛(時間=2+1=3). 排個序找出每頭牛應該排到的位置,然後可以發現交換的牛一定是屬於同一個置換循環裏,那麽對於每個循環單獨考慮 有兩種方法搞 第一是每個元素和最小的一直換
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int n = 0; char ch = *++ptr; while(ch < ‘0‘ || ch > ‘9‘) ch = *++ptr; while(ch <= ‘9‘ && ch >= ‘0‘){ n = (n << 1) + (n << 3) + ch - ‘0‘; ch = *++ptr; } return n; } typedef long long ll; const int maxn = 10000 + 10; int num[maxn], pos[maxn], a[maxn]; bool vis[maxn] = {false}; int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); int N = readint(); for(int i = 1; i <= N; i++) num[i] = a[i] = readint(); sort(a + 1, a + N + 1); for(int i = 1; i <= N; i++) pos[i] = lower_bound(a + 1, a + N + 1, num[i]) - a; ll ans = 0; for(int j, Min, tot, siz, i = 1; i <= N; i++){ if(vis[i]) continue; Min = tot = num[i]; siz = 1; vis[i] = true; j = pos[i]; while(!vis[j]){ Min = min(Min, num[j]); tot += num[j]; siz++; vis[j] = true; j = pos[j]; } ans += min((ll)Min * (siz - 2), (ll)a[1] * (siz + 1) + Min) + tot; } printf("%lld\n", ans); return 0; }
[BZOJ1697][Usaco2007 Feb]Cow Sorting牛排序