UVa 10026 - Shoemaker's Problem
题目链接:http://uva.onlinejudge.org/external/100/10026.html
题意:
一个鞋匠,必须要完成一系列工作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