UVa 10670 Work Reduction 解题报告(贪心)

Problem C: Work Reduction

Paperwork is beginning to pile up on your desk, and tensions at the workplace are starting to mount. Your boss has threatened to fire you if you don't make any progress by the end of the day. You currently have  N  units of paperwork on your desk, and your boss demands that you have exactly  M  units of paperwork left by the end of the day.

The only hope for you now is to hire help. There are various agencies which offer paperwork reduction plans:

For $A they will reduce your paperwork by one unit.
For $B they will reduce your entire paperwork by half (rounding down when necessary).

Note that work can never be reduced to less than 0.

Your task now is to produce a sorted table of agency names and their respective minimum costs to solve your workload problem.

The first line of input consists of a single positive integer representing the number of cases to follow. Each case begins with three positive integers separated by spaces: N - your starting workload, M - your target workload, and L - the number of work reduction agencies available to you, (1 <= M <= N <= 100000, 1 <= L <= 100). The next L lines have the format "[agency name]:A,B", where A and B are the rates as described above for the given agency. (0 <= A,B <= 10000) The length of the agency name will be between 1 and 16, and will consist only of capital letters. Agency names will be unique.

For each test case, print "Case X", with X being the case number, on a single line, followed by the table of agency names and their respective minimum costs, sorted in non-decreasing order of minimum costs. Sort job agencies with identical minimum costs in alphabetical order by agency name. For each line of the table, print out the agency name, followed by a space, followed by the minimum required cost for that agency to solve your problem.

Sample Input

2
100 5 3
A:1,10
B:2,5
C:3,1
1123 1122 5
B:50,300
A:1,1000
C:10,10
D:1,50
E:0,0

Sample Output

Case 1
C 7
B 22
A 37
Case 2
E 0
A 1
D 1
C 10
B 50

    解题报告:一道水题。不过输入部分不好处理。懒得自己写readInt那些,可以直接用sscanf。

    过程部分,当前的任务量大于目标的一半,那么选择最便宜的方式到达一半那里;如果小于,那么直接一个单位一个单位完成。有贪心的思想在里面。

    代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM
    work();
}

/***************************************************/

char str[111];

struct Node
{
    char name[20];
    int a, b;
    int cost;

    bool operator<(const Node& cmp) const
    {
        return cost == cmp.cost ? strcmp(name, cmp.name) < 0 : cost < cmp.cost;
    }
} node[111];

void work()
{
    int T;
    scanf("%d", &T);
    fff(cas, 1, T)
    {
        int n, m, l;
        scanf("%d%d%d", &n, &m, &l);

        ff(i, l)
        {
            scanf("%s", str);
            int len = strlen(str);

            // 将冒号改为空格,这样就可以直接用sscanf读取名字和a,b的值了。
            ff(j, len) if(str[j] == ':')
                str[j] = ' ';
            sscanf(str, "%s%d,%d", node[i].name, &node[i].a, &node[i].b);
        }

        ff(i, l)
        {
            int a = node[i].a, b = node[i].b;

            int cost = 0;
            int tot = n, tar = m;
            while(tot>tar)
            {
                if(tot/2>=tar)
                {
                    cost += min(b, a*(tot-tot/2));
                    tot = tot/2;
                }
                else
                {
                    cost += (tot-tar)*a;
                    tot = tar;
                }
            }

            node[i].cost = cost;
        }

        sort(node, node+l);

        printf("Case %d\n", cas);
        ff(i, l) printf("%s %d\n", node[i].name, node[i].cost);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值