贪心-hdu-3661-Assignments

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3661

题目大意:

给n个工人(n<=1000),A、B任务各有n种,给出各任务完成的时间。求怎样分配,使得每个工人完成一个A任务和B任务,如果它完成的时间S超过T,则需付薪S-T。求完成所有任务需要的最少付薪。

解题思路:

贪心。

先把A从大到小排序,对于每一个Ai,找到最大的Bj,使得Bj+Ai<T,也就是用一个尽量多的工时把Ai消耗掉,如果找不到,只有付费了,找到最小的Bk,使得Ai+Bk>=T.这样对于每一个Ai是最优的。整个也是最优的。

比赛训练完后,看别人的代码。超短啊,直接对A从大到小排序,然后对B从小到大排序,然后一个依次计算即可。依据对于对于B[i]来说如果A[i]+B[i]>=T,则用最小的耗费更划算,如果<T ,不用付费更好。

给出第一种思路的代码:

贪心+二分。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

vector<int>a,b;
bool cmp(int a,int b)
{
    return a>b;
}
int n,t;

int main()
{
    int i,x;
    while(scanf("%d%d",&n,&t) != EOF)
    {
        a.clear();b.clear();
        for(i = 0;i < n;i ++)
        {
            scanf("%d",&x);
            a.push_back(x);
        }
        for(i = 0;i < n;i ++)
        {
            scanf("%d",&x);
            b.push_back(x);
        }
        sort(a.begin(),a.end(),cmp); //从大到小排序
        sort(b.begin(),b.end());

        int ans = 0;
        vector<int>::iterator it;

        for(int i=0;i<n;i++)
        {
            it=lower_bound(b.begin(),b.end(),t-a[i]);//找到最小的b[j]+a[i]>=t,
            if(it==b.end()) //没找到,说明a[i]+bMax<t,后面的比a[i]小,所以肯定也小于t,不用考虑
                break;
            if(it==b.begin()) //如果恰好为第一个,必需要付费了
                ans+=a[i]+*it-t;
            else  //找到最大的b[j]使得b[j]+a[i]<t
                it--;
            b.erase(it);//把配对的删除掉
        }

        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(贪心)