這題可以用二分枚舉答案來求解,每次枚舉一個答案時我們總是選取滿足要求的每個零件的價格最小者,如果金錢能夠滿足的話就枚舉一個更大的品質,這裡最好將品質離散化,這樣就能枚舉每個點都用相應的品質對應。
代碼如下:
#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <map>using namespace std;map<int,int>mp;int fee[1005];struct Node{ char name[25], type[25]; int p, q; bool operator < (Node temp) const { return strcmp(name, temp.name) < 0; }}e[1005];struct Point{ int no, x; bool operator < (Point temp) const { return x < temp.x; } bool operator == (Point temp) const { return x == temp.x; }}p[1005];int N, M;bool Ac(int x){ int left = M, idx = -1; for (int i = 0; i <= 1000; ++i) { fee[i] = 1 << 30; } for (int i = 0; i < N; ++i) { if (i == 0) { ++idx; if (mp[e[i].q] >= x) { fee[idx] = min(fee[idx], e[i].p); } } else { if (strcmp(e[i].name, e[i-1].name) == 0) { if (mp[e[i].q] >= x) { fee[idx] = min(fee[idx], e[i].p); } } else { left -= fee[idx]; if (left < 0) { return false; } ++idx; if (mp[e[i].q] >= x) { fee[idx] = min(fee[idx], e[i].p); } } } } left -= fee[idx]; if (left < 0) { return false; } return true; }int bsearch(int l, int r){ int mid, ret = 0; while (l <= r) { mid = (l + r) >> 1; if (Ac(mid)) { ret = mid; l = mid + 1; } else { r = mid - 1; } } return ret;}int main(){ int cnt, ret; int T; scanf("%d", &T); while (T--) { scanf("%d %d", &N, &M); mp.clear(); for (int i = 0; i < N; ++i) { scanf("%s %s %d %d", e[i].name, e[i].type, &e[i].p, &e[i].q); p[i].x = e[i].q; } sort(e, e + N); sort(p, p + N); cnt = unique(p, p + N) - p; for (int i = 0; i < cnt; ++i) { mp[p[i].x] = i; } ret = bsearch(0, cnt-1); printf("%d\n", p[ bsearch(0, cnt-1) ].x); } return 0; }