您的位置:首页 > 其它

[POJ2456]Aggressive cows(贪心,二分查找)

2015-10-22 19:50 302 查看
题目链接:http://poj.org/problem?id=2456

二分+贪心

这是个求最小值最大的问题,我们二分从0到inf的数d,作为两头牛放置的距离不小于d,然后贪心判断。

首先要对x从小到大进行排序,接下来固定x[0]处必有一头牛,然后间距不小于d的时候,可以放置,一直放置,直到所有牛舍均被遍历O(n)。

如果牛被完全放置,那么返回true,并且向右确定边界,反之向左确定。

ac代码(32ms):

#include <cstdio>

const int maxn = 100010;
const int INF = 1 << 30;
int n, m;
int x[maxn];
int ll[maxn>>1], rr[maxn>>1];

inline bool scan_d(int &x) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){IsN=true;x=0;}
else x=in-'0';
while(in=getchar(),in>='0'&&in<='9') {
x*=10,x+=in-'0';
}
if(IsN) x=-x;
return true;
}

inline void printf_d(int a) {
if(a > 9) {
printf_d(a / 10);
}
putchar(a % 10 + '0');
}

void merge(int *x, int p, int m, int q) {
int n1 = m - p + 1;
int n2 = q - m;
int i = 0, j = 0;
for(int ii = 0; ii < n1; ii++) ll[ii] = x[p+ii];
for(int ii = 0; ii < n2; ii++) rr[ii] = x[m+ii+1];
while(i < n1 && j < n2) {
if(ll[i] <= rr[j]) x[p++] = ll[i++];
else x[p++] = rr[j++];
}
while(i < n1) x[p++] = ll[i++];
while(j < n2) x[p++] = rr[j++];
}

void mergesort(int *x, int p, int q) {
if(p < q) {
int m = (p + q) >> 1;
mergesort(x, p, m);
mergesort(x, m+1, q);
merge(x, p, m, q);
}
}

bool ok(int d) {
int cow = 1;
int tmp = x[0];
for(int i = 1; i < n; i++) {
if(x[i] - tmp >= d) {
cow++;
tmp = x[i];
}
}
if(cow >= m) {
return true;
}
return false;
}

int main() {
// freopen("in", "r", stdin);
while(scan_d(n) && scan_d(m)) {
for(int i = 0; i < n; i++) {
scan_d(x[i]);
}
mergesort(x, 0, n-1);
int ll = 0, rr = INF;
while(rr - ll > 1) {
int mm = (ll + rr) >> 1;
if(ok(mm)) {
ll = mm;
}
else {
rr = mm;
}
}
printf_d(ll);
putchar('\n');
}
}


对于本题取ll还是rr的问题,如果拿不准可以每次更新ll,rr的时候同时选择是否更新ans,这样就不用纠结了。二分查找的限界也可以很无脑地记住。

const int maxn = 100010;
int n, c, ans;
int x[maxn];

bool ok(int d) {
int cow = x[1];
int cnt = 1;
for(int i = 2; i <= n; i++) {
if(x[i] - cow >= d) {
cnt++;
cow = x[i];
}
}
return cnt >= c;
}

int main() {
// freopen("in", "r", stdin);
while(~scanf("%d %d", &n, &c)) {
for(int i = 1; i <= n; i++) {
scanf("%d", &x[i]);
}
int ll = 0;
int rr = 0x7f7f7f7f;
ans = 0x7f7f7f7f;
sort(x+1,x+n+1);
while(ll <= rr) {
int mm = (ll + rr) >> 1;
if(ok(mm)) {
ll = mm + 1;
ans = mm;
}
else rr = mm - 1;
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: