UVa714 例题8-10 抄书

来源:互联网 发布:iphone清理内存软件 编辑:程序博客网 时间:2024/04/29 23:37

原题链接: UVa-714

题目大意:

  现有k个抄写员,m本书,每本书有若干页,每个抄书员需要抄写连续的若干本书。现在要找出一种分配方法使得抄写页数最多的那个抄写的页数最少。(有点绕,可以自行参考原题或者紫书P244)

解题思路:

 博主一开始的思路是根据序列平均值来判断,后来感觉不是很正确,就直接参考了紫书上给的思路。大致思路就是设s(i)为每个序列的和(每个抄书员抄的页数),找到大于所有s(i)的最小值x。然后就可以根据这个x利用贪心算法得到结果。至于x的获得方法,就是利用二分法,利用P(x0)来判断x0与x的关系。具体细节参考代码。

代码:

//E8-10 UVa714 AC P244#include<iostream>#include<algorithm>#include<cstring>#include<string>using namespace std;void print(long long mx);long long find(int maxp, long long sum);int p(int num);const int MAXN = 500 + 5;int arr[MAXN], m, k, n;int main(){freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);cin >> n;while (n--) {cin >> m >> k;long long sum = 0;int maxp = 0;for (int i = 0; i < m; i++) { //输入过程中获取总和及最大值 cin >> arr[i];sum += arr[i];maxp = max(maxp, arr[i]);}print(find(maxp, sum));}return 0;}void print(long long mx)//打印 {int last[MAXN], remain = k;long long sum = 0;memset(last, 0, sizeof(last));for (int i = m - 1; i >= 0; i--) {//逆序找到每个断点处 if (sum + arr[i] > mx || i + 1 < remain) {last[i] = 1; remain--; sum = 0;}sum += arr[i];}for (int i = 0; i < m - 1; i++) {//输出 cout << arr[i] << " ";if (last[i]) cout << "/ ";}cout << arr[m - 1] << endl;}long long find(int maxp, long long sum)//找到使得大于等于所有s(i)且最小的值x {long long mx = sum, mn = maxp;while (mn < mx) {// 利用二分法找到x long long mid = (mx + mn) / 2;if (p(mid) <= 0) mx = mid;// x <= mid,向下缩短范围 else mn = mid + 1;//x > mid,向上缩短范围  }return mn;}//比价使得s(i)均不超过的x与num的关系//x > num 返回正数,x < num返回负数 ,x=num返回0int p(int num){long long sum = 0;int cnt = 1;for (int i = 0; i < m; i++) {//计算以num为最大s(i)值的情况下,能分割为多少段 if (sum + arr[i] > num) {sum = 0; cnt++;}sum += arr[i];}return cnt - k;//比较cnt 与 k }




原创粉丝点击