题目意思:
有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;
}