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;
}

 

posted @ 2015-02-04 14:26  人艰不拆_zmc  阅读(329)  评论(0编辑  收藏  举报