您的位置:首页 > 编程语言 > Go语言

Uva 714 (抄书问题,二分查找+贪心)

2017-11-10 15:31 387 查看
题目链接在

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=655

这题要求最大值尽量小,最大值越小肯定越难,所以如果最大值可以是x1的话, 那么x2>x1肯定也可以,所以这里可以用binary search。

另外还要加greedy search,从最右边开始(因为题目规定S(1) 尽量小, 若S(1)一样则S(2)尽量小…),尽量把多的数放到一起(只要sum不大于目标值即可)。

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> ans;

//test if we can divide the data array into x parts, with the max of the sum in each part not larger than x
bool P(vector<int>&data, int k, long long x) {
int p1 = data.size()-1;
long long tempSum = 0;
ans.resize(0);

while (p1 >= 0) {
while ((tempSum <= x) && (p1>=k-2)) {
tempSum += data[p1--];
}

p1++; //bounce back because p1 moves too much.

ans.push_back(p1);
k--;

if (p1<k-1) {
return false;
}

tempSum = 0;

if (k==1) {
long long sum1 = 0;
for (int i=0; i<=p1; i++) {
sum1 += data[i];
}
if (sum1 <= x) {
return true;
}
else {
return false;
}
}

}

}

int main()
{
int n,k,T;
vector<int> data;

cin>>T;
while(T--) {
long long sum = 0;
int maxi = 0;
cin>>n>>k;
data.resize(n);
for (int i=0; i<n; i++){
cin>>data[i];
sum+=data[i];
maxi=max(maxi, data[i]);
}

if (k==1) {
for (vector<int>::iterator it = data.begin(); it<data.end(); it++)
cout<<*it<<" ";
cout<<endl;
continue;
}

//binary search with P(x)
long long l = 0;
long long r = sum;

while (l<r) {
long long m = l + (r-l)/2;
if (P(data, k, m)) {
r = m;   //the answer is less than or equal to m
}
else {
l = m+1; //the answer should be larger than m
}
}

P(data, k, l);

vector<int>::reverse_iterator  r_it = ans.rbegin();
for (int i=0; i<data.size(); i++) {
cout<<data[i]<<" ";
if (i==*r_it) {
cout<<"/ ";
++r_it;
}
cout<<endl;
}
}

return 0;
}


设所有n个元素的SUM和为M, 二分次数为logM,每次整个数组都扫一遍。所以复杂度为O(nlogM)。

这题要注意跟sum有关的变量都用long long,不然可能溢出。我在Uva上提交的结果是Presentation Error。应该是结果对,但输出不符合要求。不知道具体什么原因,以后再查,欢迎有知道原因的同学留言。也欢迎大家对我的代码提出改进意见。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  algorithm-design