http://poj.org/problem?id=1042
题意:
约翰正在钓鱼之旅。他有h小时可用(1 <= h <= 16),该地区有n个湖泊(2 <= n <= 25)都可以沿着单一的单行道路到达。约翰从湖1开始,但他可以在任何他想要的湖泊完成。他只能从一个湖泊到另一个湖泊,但除非他愿意,否则他不必停在任何湖泊。对于每个i = 1,...,n-1,从湖i到湖i + 1旅行所需的5分钟间隔的数量表示为ti(0 <ti <= 192)。例如,t3 = 4表示从湖泊3到湖泊4需要20分钟。为了帮助计划他的钓鱼行程,约翰收集了关于湖泊的一些信息。对于每个湖,我知道在最初5分钟内被捕获的鱼数,表示为fi(fi> = 0)。 每5分钟的钓鱼减少预期在接下来的5分钟间隔内捕获的鱼的数量以di(di> = 0)的恒定速率。如果预计在一个间隔内被捕获的鱼数量小于或等于di,则在下一个时间间隔内不会有更多的鱼留在湖泊中。为了简化规划,约翰假定没有其他人在湖泊钓鱼,影响他预期捕捞的鱼的数量。
思路:
要想钓到尽量多的鱼,那么每次尽量去选择鱼多的湖泊里去钓鱼,但是这里又牵涉到了从一个湖泊到另一个湖泊时间的问题。
因为湖泊都是单行道路到达,所以枚举每次钓鱼到达的终点湖泊,减去到达终点湖泊的时间,那么我们就可以在这些湖泊之间任意来回钓鱼了,用优先队列来维护,每次让鱼最多的湖泊出来。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int maxn = 30; int n, h; struct node { int f, d, id; bool operator <(const node& rhs) const { return f < rhs.f || (f == rhs.f && id>rhs.id); } }a[maxn]; int t[maxn]; int ans[maxn]; int temp[maxn]; int main() { //freopen("D:\txt.txt", "r", stdin); while (~scanf("%d", &n)) { if (n == 0) break; scanf("%d", &h); h *= 12; for (int i = 1; i <= n; i++) scanf("%d", &a[i].f); for (int i = 1; i <= n; i++) { scanf("%d", &a[i].d); a[i].id = i; } for (int i = 1; i <= n - 1; i++) scanf("%d", &t[i]); int max_fish = -1; memset(ans, 0, sizeof(ans)); //枚举终点 for (int e = 1; e <= n; e++) { memset(temp, 0, sizeof(temp)); priority_queue<node> q; int t_left = h; for (int k = 1; k < e; k++) t_left -= t[k]; for (int k = 1; k <= e; k++) q.push(a[k]); int num = 0; while (t_left>0) { node p = q.top(); q.pop(); num += p.f; temp[p.id]++; t_left--; p.f = p.f - p.d; if (p.f < 0) p.f = 0; q.push(p); } if (num>max_fish) { max_fish = num; for (int i = 1; i <= e; i++) ans[i] = temp[i]; } } for (int i = 1; i <= n; i++) { printf("%d", ans[i] * 5); if (i != n) printf(", "); } printf(" "); printf("Number of fish expected: %d ", max_fish); printf(" "); } return 0; }