【贪心策略】Shoemaker‘s Problem

14 篇文章 1 订阅

Shoemaker has N jobs (orders from customers) which he must make. Shoemaker can work on only one job in each day. For each i-th job, it is known the integer Ti (1 ≤ Ti ≤ 1000), the time in days it takes the shoemaker to finish the job. For each day of delay before starting to work for the i-th job, shoemaker must pay a fine of Si (1 ≤ Si ≤ 10000) cents. Your task is to help the shoemaker, writing a programm to find the sequence of jobs with minimal total fine.

Input

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

First line of input contains an integer N (1 ≤ N ≤ 1000). The next N lines each contain two numbers: the time and fine of each task in order.

Output

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

You programm should print the sequence of jobs with minimal fine. Each job should be represented by its number in input. All integers should be placed on only one output line and separated by one space. If multiple solutions are possible, print the first lexicographically.

Sample Input

1

4

3 4

1 1000

2 2

5 5

Sample Output

2 1 3 4

题解

这道题考虑贪心。
考虑第i和i+1项工作的情况,假设前面的i-1项工作已经被安排好,那么前面的任务无论如何安排顺序,到达第i项时,罚时都是固定的。假设前面任务对于i以及i+1的罚金为F,现在就只需要考虑两者谁先谁后的问题。
若是i任务在前,对于i+1任务来说,产生 T i T_i Ti罚时,罚款为 T i ∗ S i + 1 T_i*S_{i+1} TiSi+1
若是i+1任务在前,对于i任务来说,产生 T 1 + i T_{1+i} T1+i罚时,罚款为 S i ∗ T i + 1 S_i*T_{i+1} SiTi+1
此时只需要比较 T i ∗ S i + 1 + F T_i*S_{i+1}+F TiSi+1+F S i ∗ T i + 1 + F S_i*T_{i+1}+F SiTi+1+F,化简下来就是比较 T i / S i T_i/S_i Ti/Si,结果越小越应该排在前面。

关键代码

关键就是建立排序函数
定义结构体

struct job{
    int t;
    int s;
    int num;
}jobs[1010];

定义比较函数

bool cmp(job a,job b){
    double fine1=a.t*1.0/a.s;
    double fine2=b.t*1.0/b.s;
    return fine1<fine2;
}

psps:这里比较的是除数运算之后的数!是个浮点数而不是整数,需要把整数转为浮点数才可以~ 这里是按照fine的字典序升序排列。

最后就是比较啦,记得加上头文件

#include<algorithm>
sort(jobs,jobs+n,cmp);

完成AC代码

/* UVA10026 Shoemaker's Problem 
copyright by bamboo
*/

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int N;
struct job{
    int t;
    int s;
    int num;
}jobs[1010];
bool cmp(job a,job b){
    double fine1=a.t*1.0/a.s;
    double fine2=b.t*1.0/b.s;
    return fine1<fine2;
}
int main(){
    cin>>N;
    while(N--){
        int n;
        cin>>n;
        memset(jobs,0,sizeof(jobs));
        for(int i=0;i<n;i++){
            cin>>jobs[i].t>>jobs[i].s;
            jobs[i].num=i+1;
        }
        sort(jobs,jobs+n,cmp);
        for(int i=0;i<n-1;i++) cout<<jobs[i].num<<" ";
        cout<<jobs[n-1].num<<endl;
        if(N) cout<<endl;
    }
}
  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值