题目链接:
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; }