UVa 10026 - Shoemaker's Problem

题目链接:http://uva.onlinejudge.org/external/100/10026.html

题意:

一个鞋匠,必须要完成一系列工作N <= 1000 jobs,完成第i个工作花费的时间 T_{i} ,不完成每天需要罚款 S_{i}。求全部完成,最少的罚款。

 

思路:贪心。

分析:先拿出来两个工作i,j进行比较,先做第i个,和先做第j的顺序,并不影响i,j之后的工作花费的时间和得到的罚款,所以问题分解为每两个工作比较。

那么既然比较,就要有比较的规则:

  1)首先,判断工作i,j的损失比率,比率越大就要先做,此题比率 R =  罚款/花费的时间.如果Ri > Rj,那么先做工作i,然后做工作j;如果Ri < Rj,那么先做工作j,然后做工作i;

  2)然后,假如Ri = Rj,那么就要比较先做哪个工作会被罚更多,

    <1>设先做i,那么做完i,j需要花费CostA = Ti*Si  + Tj  * (Si + Sj); Ti * Si是做工作i时被罚款金额,Tj*(Si+Sj)是做j的时候被罚款金额。  

    <2>设先做j,那么做完i,j需要花费CostB = Tj*Sj  + Ti  * (Si + Sj); Tj * Sj是做工作j时被罚款金额,Ti*(Si+Sj)是做i的时候被罚款金额。

  比较CostA和CostB,如果CostA > CostB,那么先做工作i,然后做工作j;如果CostA < CostB,那么先做工作j,然后做工作i。

  3)最后,如果Costi = Costj,那么按Ti,Tj的大小,由小到大排序。即如果Ti < Tj,先做工作i,然后做工作j;如果Ti > Tj,先做工作j,然后做工作i。

 

具体实现可以使用C++的STL函数sort(),设计编写函数的比较函数bool compare();

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define MAXN 1000+10

struct Jobs{
    int _num;
    int _time;
    int _fine;
    double _rank;
};
bool cmp(const Jobs &a,const Jobs &b){
    if(a._rank > b._rank)
        return true;
    else if(a._rank == b._rank){
        if(a._fine * a._time + b._fine * (a._time + b._time)
           > b._fine * b._time + a._fine*(a._time + b._time))
            return true;
        else if(a._fine * a._time + b._fine * (a._time + b._time)
           < b._fine * b._time + a._fine*(a._time + b._time)){
            if(a._time < b._time)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    else
        return false;
}

class Shoemaker{
    private:
        int jobNum;
        Jobs jobs[MAXN];
    public:
        void process();
};

void Shoemaker::process(){
    int cases;
    cin>>cases;
    while(cases--){
        cin>>jobNum;
        for(int i = 0;i < jobNum;i++){
            jobs[i]._num = i + 1;
            cin>>jobs[i]._time>>jobs[i]._fine;
            double t = (double)jobs[i]._fine/(double)jobs[i]._time;
            jobs[i]._rank = t;
        }
        sort(jobs,jobs+jobNum,cmp);
        for(int i = 0;i < jobNum;i++){
            cout<<jobs[i]._num;
            if(i < jobNum - 1)cout<<" ";
        }
        cout<<endl;
        if(cases>0)cout<<endl;
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("D:\\acm.txt","r",stdin);
    #endif // ONLINE_JUDGE
    Shoemaker shoemaker;

    shoemaker.process();
    return 0;
}

 测试数据:不要点击复制按钮,直接在页面选择复制,否则会导致数据缺失。

数据来源:http://www.algorithmist.com/index.php/UVa_10026

Input

4

4
3 4
1 1000
2 2
5 5

3
1 1
2 2
3 3

5
3 2
3 5
9999 9998
2 3
10000 10000

3
123 123
3 3
5 5

 

Output

2 1 3 4

1 2 3

2 4 5 3 1

1 2 3
posted @ 2015-05-10 00:53  小白v  阅读(204)  评论(0编辑  收藏  举报