UVA10026:Shoemaker's Problem(贪心)
题目链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68990#problem/K
题目需求:鞋匠有n个任务,第i个任务要花费ti天,同时第i个任务每耽误一天要有fi的罚金。求完成所有任务的最小罚金。
题目解析:
这题看了题解,解法如下:
这个是一个贪心的题目首先按照fine/time降序排列,值相同的再按序号升序排列。
对于为什么贪心策略是这个样子的,我们不妨拿相邻的两个事件a、b来说明一下。由于a、b之后的事件是固定的,所以我们无论排成ab还是排成ba后面部分的损失都是固定的,那么损失的差别主要来源于究竟是排成ab还是排b成a。排ab的损失为ta*fb,排ba的损失为tb*fa,那么如果ta*fb<tb*fa,我们就排成ab,这样可以得到fa/ta>fb/tb,推而广之,就得到了我们的贪心策略。
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <math.h> #include <queue> #define eps 1e-9 typedef long long ll; using namespace std; struct node { int we; double t,s,z; }q[1010]; int n; int cmp(const void *a,const void *b) { struct node *aa=(struct node *)a; struct node *bb=(struct node *)b; if(bb->z!=aa->z) return bb->z>aa->z; else return aa->we-bb->we; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lf%lf",&q[i].t,&q[i].s); q[i].we=i+1; q[i].z=(q[i].s*1.0)/q[i].t; } qsort(q,n,sizeof(q[0]),cmp); printf("%d",q[0].we); for(int i=1;i<n;i++) { printf(" %d",q[i].we); } cout<<endl; if(T!=0) cout<<endl; } return 0; }