题意:
一个鞋匠,必须要完成一系列工作N <= 1000 jobs,完成第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