Fork me on GitHub

UVA 12382 Grid of Lamps --贪心+优先队列

题意:给出每行每列至少有的灯泡数,问最少有的灯泡数。

解法:要使灯泡数尽量小,说明要使交叉点尽量多,这样即抵了行,又抵了列,为最优的。所以可以用行来消去列,也可以用列来消去行,我这里是列来消去行。首先将列的灯泡数排个序,从大到小枚举,同时每次行的数也要有序,可以直接排序或者用优先队列,然后一个一个消去,最后加上两个部分还剩下的即是答案。

注意优先队列不要搞多了,比如用来过渡的队列不要用优先队列,因为优先队列还要排序,会超时的。

 

代码:

#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;
}
View Code
posted @ 2014-07-21 19:43  whatbeg  阅读(586)  评论(0编辑  收藏  举报