POJ2010 Moo University - Financial Aid —— 二分答案+巧妙的判断

二分答案,但是这里的判断不同于一般的二分。

分别将cows和cowc按照s和c排序。

我的代码里check函数的返回值含义如下:

-1 直接输出,不可能满足条件了

0 这种方案是满足条件的,可以把中位数调大试试

1 这种方案是不满足的,但是把中位数调大就有可能满足了(否则不可能满足)

2 这种方案是不满足的,但是把中位数调小就有可能满足了(否则不可能满足)

还是不会用cpp,用了switch语句却没写break,导致纠结了好长时间。

终于给家里台式机装上Ubuntu了,才发现NOI Linux就是害人用的啊。

 

参考代码

# include <cstdio>

# include <iostream>

# include <cstring>

# include <algorithm>

using namespace std;

const int maxN=100005;

struct Node{ int c,s,id; };

int n,m,tot;

Node cows[maxN],cowc[maxN];



bool cmps(Node a,Node b) { return a.s<b.s; }

bool cmpc(Node a,Node b) { return a.c<b.c; }



int check(int limit)

{

	int left=0,right=0,all=cows[limit].c;

	for (int i=0;i<n;i++){

		if ((cowc[i].id<limit)&&(all+cowc[i].c<=tot)&&(left<m/2)){

			all+=cowc[i].c;left++;

		} else if ((cowc[i].id>limit)&&(all+cowc[i].c<=tot)&&(right<m/2)){

			all+=cowc[i].c;right++;

		}

	}

	if ((left<m/2)&&(right<m/2)) return -1;

	else if (left<m/2) return 1;

	else if (right<m/2) return 2;

	else return 0;

}



int main()

{

	scanf("%d%d%d",&m,&n,&tot);

	for (int i=0;i<n;i++) scanf("%d%d",&cows[i].s,&cows[i].c);

	sort(cows,cows+n,cmps);

	for (int i=0;i<n;i++) cows[i].id=i;

	memcpy(cowc,cows,sizeof(cows));

	sort(cowc,cowc+n,cmpc);

	int l=1,r=n,ans=-1;

	while (l<=r){

		int mid=(l+r)>>1;

		switch (check(mid)){

			case -1: { printf("-1\n"); return 0; }

			case  0: { ans=cows[mid].s; l=mid+1; break; }

			case  1: { l=mid+1; break;}

			case  2: { r=mid-1; }

		}

	}

	if (ans>=0) printf("%d\n",ans); else printf("-1\n");

	return 0;

}

 

你可能感兴趣的:(poj)