题意:给出每行每列至少有的灯泡数,问最少有的灯泡数。
解法:要使灯泡数尽量小,说明要使交叉点尽量多,这样即抵了行,又抵了列,为最优的。所以可以用行来消去列,也可以用列来消去行,我这里是列来消去行。首先将列的灯泡数排个序,从大到小枚举,同时每次行的数也要有序,可以直接排序或者用优先队列,然后一个一个消去,最后加上两个部分还剩下的即是答案。
注意优先队列不要搞多了,比如用来过渡的队列不要用优先队列,因为优先队列还要排序,会超时的。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; #define N 1017 priority_queue<int> R; queue<int> tmpR; int a[N],b[N]; int main() { int n,m,t,i,j,c; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i] > 0) R.push(a[i]); } for(i=1;i<=m;i++) scanf("%d",&b[i]); int sum = 0; sort(b+1,b+m+1); for(i=m;i>=1;i--) { if(b[i] == 0) break; while(!R.empty()) { if(b[i] == 0) break; int v = R.top(); R.pop(); if(v > 0) { v--; b[i]--; if(v > 0) tmpR.push(v); sum++; } } while(!tmpR.empty()) { R.push(tmpR.front()); tmpR.pop(); } } while(!R.empty()) { sum += R.top(); R.pop(); } for(i=1;i<=m;i++) if(b[i]) sum += b[i]; printf("%d\n",sum); } return 0; }