题意:有N项工作,每项工作完成需要n天,如果不开始做每天罚fee,开始做即不罚钱,求任务的执行顺序,使得罚钱最少.如果有多组答案,取下标排列最小的那组
解题思路:
考虑工作tn(dn,fn) ,
假如先做工作tj, 0<j<n,0<i<n,那么罚的钱是 dj*f0+dj*f1+.....dj*fn+dj*fi = totalj1,
在做工作ti, di*f0+di*f1+....di*fn = totalj2, totalj1 + totalj2 = (di+dj)*fo + (di+dj)*f1 +....(di+dj)fn + (dj*fi)
假如先做工作ti,0<i<n,那么罚的钱是 di*f0+di*f1+....di*fn+di*fj = totali1,
再做tj,dj*f0+dj*f1+.....dj*fn=totali2, totali1+totali2 = (di+dj)*fo + (di+dj)*f1 +....(di+dj)fn +(di*fj)
差别就是di*fj和dj*fi
#include <algorithm> #include <iostream> namespace cc { using std::cin; using std::cout; using std::endl; using std::move; using std::qsort; const int N = 1000; class Node { public: int fee; int day; int index; Node(int fee, int day, int index) : day(day), fee(fee), index(index) { } Node() = default; }; int cmp(const void *a, const void *b) { Node *n1 = (Node *)(a); Node *n2 = (Node *)(b); int total1 = n1->fee * n2->day; int total2 = n2->fee * n1->day; if (total1 == total2) { return n1->index - n2->index; } if (total1 < total2) return 1; return -1; } void solve() { int n; cin >> n; int t = 0; while (n--) { if(t!=0) cout<<endl; ++t; int k; cin >> k; int fee, day; int total = 0; Node nodes[N]; for (int i = 0; i < k; i++) { cin >> day >> fee; Node node(fee, day, i + 1); nodes[total++] = node; } qsort(nodes, total, sizeof(Node), cmp); cout << nodes[0].index; for (int i = 1; i < total; i++) cout << " " << nodes[i].index; cout << endl; } } } // namespace cc int main() { #ifndef ONLINE_JUDGE freopen("/Users/caicai/in", "r", stdin); #endif // !ONLINE_JUDGE cc::solve(); return 0; }