【ICPC-98】uva 10670 - Work Reduction

点击打开链接uva 10670

 

题目意思:

有N个文件需要处理,现在老板要求在某天之后这些文件只能剩下M个,否则你就被炒鱿鱼了。现在没办法只有雇别人在做了,现在呢有两种工人A 和 B。A工人是付费给他A,他帮你处理一个文件,B工人是付费给他B帮你处理一半的文件。由于雇佣公司很多有L家,所以你为了能够省钱右不被老板炒鱿鱼所以就开始计算到底雇哪一家才能够最省钱呢,所以你现在目的就是要对这些公司所需要的付费进行排序输出。

 

解题思路:

1:贪心
2:分析如下:假设当前有n个文件,那么n->n/2这个过程就有两种方案,第1是直接雇A,那么代价就是(n-n/2)*A; 第二种方案就是雇B,那么代价就是B。这个时候我们要去比较哪一种方案的代价最小那么我们就选择哪种方案。当n/2<m时候说明只能够通过第一种方案了,那么这个时候加上剩下的代价然后退出即可。
3:注意事项:1 题目明确指出是向下取整,比如25/2,那么我们下一步要处理的文件就是12不是13   2输入数据的处理,这里我用的是split函数来分割,然后用sscanf来读取。

 

代码:

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define MAXN 110

int t;
int n , m , l;
struct agency{
    char name[20];
    int cost;
    int A;
    int B;
}s[MAXN];

bool cmp(agency a1 , agency a2){
    if(a1.cost < a2.cost) return true;
    else if(a1.cost == a2.cost && strcmp(a1.name,a2.name) < 0) return true;
    return false;    
}

void solve() {
    int i , j;
    int tmp_n , r , half;
    for(i = 0 ; i < l ; i++){
        s[i].cost = 0 ; tmp_n = n ;
        while(1){
            if(tmp_n/2 < m) {
                s[i].cost += (tmp_n-m)*s[i].A;
                break;
            }
            half = tmp_n/2;
            r = tmp_n-half;
            if(r*s[i].A < s[i].B)
                s[i].cost += r*s[i].A;
            else
                s[i].cost += s[i].B;
            tmp_n /= 2;
        }
    }
    sort(s , s+l , cmp);
    for(i = 0 ; i < l ; i++)
        printf("%s %d\n" , s[i].name , s[i].cost);
}

int main() {
    //freopen("input.txt" , "r" , stdin);
    int i , j , k;
    char ch[100];
    scanf("%d%*c" , &t);
    for(i = 1 ; i <= t ; i++){
        scanf("%d%d%d%*c" , &n,&m,&l);
        for(j = 0 ; j < l ; j++){
            gets(ch);
            const char *split = ":";
            char *p ; p = strtok(ch ,split);
            while(1){
                strcpy(s[j].name , p);
                p = strtok(NULL ,split);
                sscanf(p , "%d,%d" , &s[j].A , &s[j].B);
                break;
            }
        }
        printf("Case %d\n" , i);
        solve();
    } 
    return 0;
}

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值