首页 > 代码库 > 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