题目链接:hdu 4864
其实就是个贪心,只是当初我想的有偏差,贪心的思路不对,应该是这样子的:
因为 xi 的权值更重,所以优先按照 x 来排序,而这样的排序方式决定了在满足任务(即 xi >= xj && yi >= yj)的所有机器中(设为 S)优先选择更贴近 yj 的 yi(因为我们肯定是选择最贴近任务 x,y 值的机器,要么是 xi 最贴近,要么是 yi 最贴近),这样子可以使得浪费最小——因为在后续的任务中,xj 只会越来越小,S 中的任何一台机器的 xi 值都能满足要求,但 yj 就不一定了,因为一开始是按照 x 来排序的,所以 yj 有可能会比之前的更大,因此我们为当前任务选择机器时 yi 能小则小,把 yi 更大的机器留给后续有可能满足的任务,这样子就可以使得当前的浪费最小。
用个数组来作标记,整个程序就是近乎 O(n) 的复杂度了:

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 const int N = 100005; 7 8 struct node { 9 int x,y; 10 node() {} 11 node(int x, int y): x(x), y(y) {} 12 bool operator < (const node &n2) const { 13 if(x == n2.x) return y > n2.y; 14 return x > n2.x; 15 } 16 void read() { scanf("%d %d",&x,&y); } 17 } mach[N], task[N]; 18 19 int c[102]; 20 21 int main() { 22 int n,m; 23 while(~scanf("%d %d",&n,&m)) { 24 for(int i = 0; i < n; ++i) 25 mach[i].read(); 26 for(int i = 0; i < m; ++i) 27 task[i].read(); 28 sort(mach, mach + n); 29 sort(task, task + m); 30 memset(c, 0, sizeof c); 31 int num = 0; 32 ll ans = 0; 33 for(int i = 0, j = 0; j < m; ++j) { 34 while(i < n && mach[i].x >= task[j].x) { 35 c[mach[i].y]++; 36 ++i; 37 } 38 for(int k = task[j].y; k <= 100; ++k) { 39 if(c[k]) { 40 ++num; 41 ans += 500 * task[j].x + 2 * task[j].y; 42 --c[k]; 43 break; 44 } 45 } 46 } 47 printf("%d %I64d ",num,ans); 48 } 49 return 0; 50 }