noip模擬賽 天天寄快遞
阿新 • • 發佈:2017-09-23
mes break 一道 輸出 貪心算法 for pac 算法 貢獻
分析:並不是特別難的一道題,用到了貪心算法.
首先可以明確的一點是我們要盡量偷貢獻最大的數據,要先滿足每一個公司的貢獻都大於等於K,以這個作為首要條件.那麽我們可以先把每個快遞公司的快遞按照貢獻從大到小排序,每次選貢獻最大的,滿足要求了就考慮下一個快遞公司,如果過程中用超過了s個或者處理完後發現還有快遞公司沒有滿足要求就輸出無解.
上面只是滿足了第一個要求,這時可能s個還沒有用滿,那麽我們在按照貢獻全體排一次序,看哪些沒有用加上去就好了.
中途犯了一個很愚蠢的錯誤:直接把vis數組賦值為i,其實這是不對的,每一個vis應該對應快遞的ID,而不是排序後的i!
#include <cstdio> #include<cstring> #include <iostream> #include <algorithm> using namespace std; int n, m, s, k; long long ans,tot, cnt, sum, cnt2; bool flag = false,can[200010]; struct node { long long e, t; bool vis; }a[200010]; bool cmp1(node a, node b) { if (a.e == b.e) return a.t < b.t; //實際上是看誰的貢獻最大 return a.e < b.e; } bool cmp2(node a, node b) { return a.t < b.t; } int main() { scanf("%d%d%d%d", &n, &m, &s, &k); for (int i = 1; i <= m; i++) { long long e, t; scanf("%lld%lld", &e, &t); if (2 - t < 0) { a[++tot].e = e; a[tot].t = 2 - t; } } sort(a + 1, a + 1 + tot, cmp1); if (a[tot].e < n) { printf("-23333333\n"); return 0; } for (int i = 1; i <= tot; i++) { if (can[a[i].e]) continue; sum -= a[i].t; cnt++; a[i].vis = 1; if (cnt > s) { flag = 1; break; } if (sum >= k) { ans += sum; sum = 0; can[a[i].e] = 1; } } for (int i = 1; i <= n; i++) if (!can[i]) { flag = 1; break; } if (flag) printf("-23333333\n"); else { sort(a + 1, a + tot + 1, cmp2); for (int i = 1; i <= tot; i++) { if (!a[i].vis) { cnt++; ans -= a[i].t; if (cnt == s) break; } } printf("%lld\n", ans); } return 0; }
noip模擬賽 天天寄快遞