10026 - Shoemaker's Problem(贪心)

该题是说有n个任务,每个任务都有一个需要的时间,还有一个价格,这个价格的意思是:在开始处理该任务之前的每一天都亏损这个价格,问最小亏损的安排是什么样的。

YY了一下,发现样例是按照:价格/时间 进行了排序,其次按照编号排序。

大概的原理类似于性价比之类的吧,从样例就可以看出来,不一定要先处理价格高的就好,还有完成天数的限制。

至于这个贪心方法的证明,网上搜到一个:对于为什么贪心策略是这个样子的,我们不妨拿相邻的两个事件ab来说明一下。由于ab之后的事件是固定的,所以我们无论排成ab还是排成ba后面部分的损失都是固定的,那么损失的差别主要来源于究竟是排成ab还是排ba。排ab的损失为ta*fb,排ba的损失为tb*fa,那么如果ta*fb<tb*fa,我们就排成ab,这样可以得到fa/ta>fb/tb,推而广之,就得到了我们的贪心策略。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-6;
const int maxn = 1000;
int T,n,m;
struct node{
    double t,v,cc;
    int id;
    bool operator < (const node& rhs) const {
        if(fabs(cc - rhs.cc)>eps) return cc > rhs.cc;
        else return id < rhs.id;
    }
}a[maxn];
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        for(int i=0;i<n;i++) {
            scanf("%lf%lf",&a[i].t,&a[i].v);
            a[i].id = i+1;
            a[i].cc = a[i].v / a[i].t;
        }
        sort(a,a+n);
        printf("%d",a[0].id);
        for(int i=1;i<n;i++) printf(" %d",a[i].id);
        printf("\n");
        if(T) printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值