标签:style color os io for ar amp size
题意:有n个人围成一个圈,其中第i个人想要ri个不同的礼物。求最少需要多少种礼物,使得相邻的人的礼物都不相同。
思路:这是大白上面的一道贪心题目。想法挺好的。
首先如果n为偶数时,只要找出相邻两个人的r值最大,就是所需的最少的礼物数量。如果为奇数时,那情况就不一样了,因为当第1个和第n个都是奇数,按照上面的方法,他们的礼物种类是一样的,就不符合题意。那么我们可以按照第一个人所需要的礼物数量为基准划分区间。假设最坏情况下的礼物总数为R = max(ri) * 3,所以区间划分为【1,r1】,【r1 + 1,R】。所以只要记录每个人在这两个区间内取了几个,分别用front[i],back[i]表示。最后在判断是否符合,也就是第n个人是否在【1,r1】内取礼物。注意特判n == 1时的情况。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 100010; int arr[MAXN], front[MAXN], back[MAXN]; int n; int judge(int num) { int x = arr[1], y = num - arr[1]; front[1] = x; back[1] = 0; for (int i = 2; i <= n; i++) { if (i % 2 == 1) { back[i] = min(y - back[i - 1], arr[i]); //尽量往后取 front[i] = arr[i] - back[i]; } else { front[i] = min(x - front[i - 1], arr[i]); //尽量往前取 back[i] = arr[i] - front[i]; } } return front[n] == 0; } int main() { while (scanf("%d", &n) == 1 && n) { for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); if (n == 1) { printf("%d\n", arr[1]); continue; } arr[n + 1] = arr[1]; int L = 0, R = 0; for (int i = 1; i <= n; i++) L = max(L, arr[i] + arr[i + 1]); memset(front, 0,sizeof(front)); memset(back, 0,sizeof(back)); if (n % 2 == 1) { for (int i = 1; i <= n; i++) R = max(R, arr[i] * 3); while (L < R) { int mid = L + (R - L) / 2; if (judge(mid)) R = mid; else L = mid + 1; } } printf("%d\n", L); } return 0; }
UVA1335-- Beijing Guards,布布扣,bubuko.com
标签:style color os io for ar amp size
原文地址:http://blog.csdn.net/u011345461/article/details/38403329