题目大意:有N个湖泊只有一条通路将这些湖泊相连。每个湖泊都会给最开始5分钟间隔内可以调到的鱼(f),然后给每过5分钟减少的鱼的数量(d),如果当前的鱼少于等于减少的数量,说明在下个5分钟没有鱼。还有过每条道路的所要耗费的时间(N-1),时间都是以5分钟为单位的。渔者可以在任意一个湖泊钓鱼,但是起始位置是在湖泊1。问H小时后,渔者怎样合理的在每个湖泊分配时间,可以得到的鱼最多。如果得到最多的鱼的方式有多种,则取在前面的湖泊耗时最久的那一种。
解题思路:因为这些湖泊是由一条通路串起来的,这样就意味着经过湖泊3,那么的先经过湖泊2。
所以这里先枚举钓鱼的终点i,这样在路上耗费的时间就可以确定了,然后在0 - i这些湖泊中以f最大的排序。每次取都是f取最多的,直到和这个湖泊的鱼减少到和第二个大的f相等或者更小。这里有个注意点,两个湖泊如果f相同的话,应该先选比较前面的湖泊。
然后再进行排序,重复这些操作直到时间耗尽,或是没有湖泊有鱼。
这样就可能存在时间没有用完的情况,这个时候任意的湖泊都是没有鱼的,在哪个湖泊呆着都是一样的,但是因为要求的前面的湖泊耗时多,所以剩下的时间就都给湖泊1。
最后统计鱼的时候,大于当前的最大值自然要保存这种分配方式,但是等于的话,就需要选择前面湖泊耗时较大的那种。
计算鱼的数量时候要细心。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 30; int h, n; int t[N]; typedef long long ll; ll fish; struct Lake { int i; ll f; int d; int hour; }l[N], l1[N]; int cmp (const Lake &a, const Lake &b) { if (a.f == b.f) return a.i < b.i; return a.f > b.f; } int cmp1 (const Lake &a, const Lake &b) { return a.i < b.i; } void init () { h *= 12; fish = -1; for (int i = 0; i < n; i++) l[i].hour = 0; } bool judge (int num, int newh) { //相同鱼的数目的时候比较选择哪种方案 sort (l1, l1 + num + 1, cmp1); l1[0].hour += newh; for (int i = 0; i <= num; i++) if (l1[i].hour != l[i].hour) return l1[i].hour > l[i].hour; return false; } void solve () { init (); int newh; int k, max_day; ll sum; for (int i = 0; i < n; i++) { //枚举终点 newh = h; for (int j = 0; j <= i; j++) { l1[j].i = l[j].i; l1[j].f = l[j].f; l1[j].d = l[j].d; l1[j].hour = 0; } for (int j = 0; j <= i - 1; j++) //路上要耗费的时间 newh -= t[j]; if (newh <= 0) continue; //到达不了直接下一种方案 if (i == 0) { l1[i].hour += newh; newh = 0; } while (newh > 0 && i) { //找f最大的湖泊 sort (l1, l1 + i + 1 , cmp); if (l1[0].f == 0) break; if (l1[0].d != 0) { if (l1[0].f == l1[0].f) k = 1; else { k = (l1[0].f - l1[1].f) / l1[0].d; if ((l1[0].f - l1[1].f) % l1[0].d) k++; } } else k = newh; //如果d等于0说明这里的鱼不会减少,自然剩下的时间都耗费在这里最合理。 if (newh - k < 0) k = newh; newh -= k; l1[0].f -= k * l1[0].d; //更新f和这个湖泊的耗时 if (l1[0].f < 0) l1[0].f = 0; l1[0].hour += k; } sum = 0; for (int j = 0; j <= i; j++) { //计算鱼的数目 k = l1[j].i; if (!l1[j].hour) continue; if (l[k].d == 0) { sum += l[k].f * l1[j].hour; continue; } max_day = l[k].f/ l[k].d; if (l[k].f % l[k].d != 0) max_day++; if (l1[j].hour <= max_day) max_day = l1[j].hour; l1[j].f = l[k].f - (max_day - 1) * l[k].d; sum += (l[k].f + l1[j].f) * max_day / 2; } if (sum > fish || (sum == fish && judge(i, newh))) { //维护最大值 fish = sum; for (int j = 0; j <= i; j++) { if (l1[j].i == 0) l[0].hour = l1[j].hour + newh; else l[l1[j].i].hour = l1[j].hour; } } } } int main () { bool flag = 0; while (scanf ("%d", &n) && n) { if (flag) printf ("\n"); flag = 1; scanf ("%d", &h); for (int i = 0; i < n; i++) scanf ("%lld", &l[i].f); for (int i = 0; i < n; i++) scanf ("%d", &l[i].d); for (int i = 0; i < n - 1; i++) scanf ("%d", &t[i]); for (int i = 0; i < n; i++) l[i].i = i; solve(); printf ("%d", l[0].hour * 5); for (int i = 1; i < n; i++) printf (", %d",l[i].hour * 5); printf ("\n"); printf ("Number of fish expected: %lld\n", fish); } return 0; }
uva757 - Gone Fishing(贪心)
时间: 2024-10-15 12:17:52