题目大意:N 份工作要求下班时正好剩余 M,现在有 L 家代理公司可供选择。每家代理公司都有两种方案,一种是解决一份花费A,另一种是解决当前工作量的一半(四舍五入)花费B,问每家公司的最小花费。输出按照费用升序,费用相同的情况下按照公司名称的字典序。
解题思路:贪心,选择当前最优方案即可。先计算一下当前工作量的一半是多少件,判断减去这些是否还大于 M,如果不是直接选择一件一件减到 M 就可以了。比较一下两种方案的花销选择费用小的。注意四舍五入是 (int)(n/2.0+0.5)。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<string.h>
using namespace std;
struct agency {
char name[20];
int A, B, cost;
};
agency ag[110];
int T, N, M, L;
bool cmp(agency a, agency b) {
if (a.cost != b.cost)
return a.cost < b.cost;
return strcmp(a.name, b.name) < 0;
}
void f(int i, int n, int m) {
while (n > m) {
int tmp = (int)(n/2.0+0.5);
if (n-tmp >= m && ag[i].A*tmp >= ag[i].B) {
ag[i].cost += ag[i].B;
n -= tmp;
}
else {
ag[i].cost += ag[i].A;
n--;
}
}
}
int main() {
scanf("%d", &T);
for (int t = 0; t < T; t++) {
scanf("%d%d%d", &N, &M, &L);
for (int i = 0; i < L; i++) {
char tmp[200];
scanf("%s", tmp);
int j;
for (j = 0; tmp[j] != ':'; j++)
ag[i].name[j] = tmp[j];
ag[i].name[j] = '\0';
sscanf(tmp+j+1, "%d,%d", &ag[i].A, &ag[i].B);
ag[i].cost = 0;
}
for (int i = 0; i < L; i++)
f(i, N, M);
sort(ag, ag+L, cmp);
printf("Case %d\n", t+1);
for (int i = 0; i < L; i++)
printf("%s %d\n", ag[i].name, ag[i].cost);
}
return 0;
}
思路不难,WA 了几发。一是四舍五入的写法(int)(n/2+0.5),n 是 int 所以这种写法答案是错的。还有因为是四舍五入的,剩余工作量应该是 n -= tmp,一开始直觉写的是一半 n = tmp,失了志