首页 > 代码库 > SGU 543 Cafe

SGU 543 Cafe

题意:

n个队伍  每队ai个人  每张桌子有t个位置  坐在每张桌子上的人必须至少有一个同队的人  问  最少需要多少桌子

思路:

由于这题的限制只有同桌同队一个  自然想到坐的时候应该两两成组去坐  不过有些队伍可能是奇数人数  这样会分出一些3来

在考虑桌子  明显我们比较喜欢偶数座位的桌子  毕竟人在分组时候2的组比3的组常规一些  如果桌子是奇数座位  我们希望先坐下一组3人  这样座位就变成偶数了

对于偶数座位的桌子  坐的方案应该是先坐偶数个3  因为3比较不好处理让它们两两一组比较好  而且这样可以尽量坐满座位  然后坐人数为2的组  最后如果还有空  我们把3的组往里尽量插  这样最大限度的利用了桌子

对于奇数座位的桌子  如果我们没有3能让它变成偶数  那么也就是说我们现在只有2  那就浪费一个座位好了

综上YY  我们可以得出方案:

1、将人分组  这时会分出一些3  然后所有的队伍全都变成偶数人数了

2、如果桌子是奇数的  那么用刚才分出的3去将桌子变成偶数  如果3不够用  那么我们去拆队伍中的6  尽量把桌子都变成偶数(记住这里是尽量  也就是说当只有1个奇数桌子的时候  并不去拆6  因为现在队伍全是偶数  可以全分成2的组  奇数那张桌子最多也就浪费1个座位  但是如果你拆了6就会多出一个3  这样可能使使用的桌子数变多!!)

3.1、如果还有奇数的桌子  说明现在一定没有3了  那么就把2尽量放就好了

3.2、如果没有奇数的桌子  那么这时可能有3  因此对于所有的桌子(现在都是偶数)  我们采用刚才说的策略  即先偶数3再尽量2最后还有空位就插3

在方案确定后  我们只需要二分桌子数  判断这个桌子数可不可行即可

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
#define N 2010

int n, t;
int a[N], b[N];

bool yes(int m) {
	int i, num3 = 0, num2 = 0, table1, table2, tablesize1, tablesize2;
	if (t & 1)
		table1 = m, table2 = 0, tablesize1 = t, tablesize2 = t - 3;
	else
		table1 = 0, table2 = m, tablesize1 = 0, tablesize2 = t;
	for (i = 1; i <= n; i++) {
		b[i] = a[i];
		if (b[i] & 1) {
			b[i] -= 3; //b all even
			num3++;
		}
	}
	if (table1) {
		if (num3 >= table1) { //3 enough
			num3 -= table1;
			table2 = table1;
			table1 = 0;
		} else {

			for (i = 1; i <= n; i++) { //cut 6
				while (b[i] >= 6) {
					b[i] -= 6;
					num3 += 2;
					if (num3 + 1 >= table1)
						break;
				}
				if (num3 + 1 >= table1)
					break;
			}
			if (num3 >= table1) {
				num3 -= table1;
				table2 = table1;
				table1 = 0;
			} else {
				table1 -= num3;
				table2 += num3;
				num3 = 0;
			}
		}
	}
	for (i = 1; i <= n; i++)
		num2 += b[i] / 2;
	if (table1) {
		while (table1--) {
			num2 -= tablesize1 / 2;
			if (num2 <= 0)
				return true;
		}
		while (table2--) {
			num2 -= tablesize2 / 2;
			if (num2 <= 0)
				return true;
		}
	} else {
		int first3 = tablesize2 / 3;
		int now;
		if (first3 & 1)
			first3--;
		while (table2--) {
			if (first3 <= num3) {
				num3 -= first3;
				now = tablesize2 - first3 * 3;
			} else {
				now = tablesize2 - num3 * 3;
				num3 = 0;
			}
			int two = now / 2;
			if (two <= num2) {
				num2 -= two;
				now -= two * 2;
			} else {
				now -= num2 * 2;
				num2 = 0;
			}
			while (num3 && now >= 3) {
				now -= 3;
				num3--;
			}
			if (!num2 && !num3)
				return true;
		}
	}
	return false;
}

int main() {
	int l, r, mid, ans;
	scanf("%d%d", &n, &t);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	l = 0;
	r = 10000000;
	while (l <= r) {
		mid = (l + r) >> 1;
		if (yes(mid)) {
			ans = mid;
			r = mid - 1;
		} else
			l = mid + 1;
	}
	printf("%d\n", ans);
	return 0;
}


SGU 543 Cafe