题目连接:757 - Gone Fishing
题目大意:有N个湖, 每个湖在单位时间内可以钓到s[i]条鱼, 但是每在这个湖钓一次鱼,下次钓到的鱼就会减少d[i]只(每次, 直到可以钓到的鱼数为0), 现在给出限定时间,以小时的形式, 题目中的单位时间为5分钟,输出的时候要转换成分钟。然后每个湖之间有一定的距离(距离给出的是该路程所需要的单位时间数)。要求在给定的时间钓到最多的鱼,并输出方案。(ps, 只能一直往下个湖泊移动, 不能回到原先的湖泊)。
输入部分:n(湖泊数, 为0时终止), h(限定时间,小时), s[i](n个数,为对应湖泊当前每次可钓到的鱼数), d[i](n个数,为每个湖泊钓一次之后钓鱼数减少的量),dist[i](n - 1个数,为两两湖泊之间移动所需的单位时间,注意这里是单位时间)
输出部分:rec[i](n 个数,对应为在该湖泊呆的时间),Max(可以调到的最大鱼量),每两组数据间空行。
解题思路:贪心的方法。
1、在哪个湖钓的鱼多,肯定先在哪一个湖泊钓,因为你在这个湖泊钓的时候其它湖泊的鱼并不会减少, 所以并不会影响到下次钓鱼时最大量的迁移。
2、对于时间,是题目已经给定好的, 但是每两个湖泊之间移动需要时间, 如果移动,总的钓鱼时间会减少,所以如何解决移动与否是题目的关键。
3、其实题目中给出的不能返回上一个湖泊是用来误导大家的, 因为每个湖泊鱼量减少是不相关的,也就是独立的问题,所以我们只需要考虑说钓鱼的这个人最后在哪个湖泊停止就好,枚举出n种可能,每种可能有它自己的最大值,在这n种情况的最大值中的最大值就是最优解。
4、先在问题转换成钓鱼的人在1-i个湖泊钓鱼的最大鱼量,那也就是默认钓鱼的人一定会走到第i个湖,即,走的路程时间是一定要用的,所以可以拿总得时间减掉路程的时间所得到的time就是他可以钓鱼的时间了,而且因为路程已经走过了, 只要到纯的贪心拿最多的就好了,转化成实际问题只是把走路和钓鱼的时间调换考虑了一下,并不影响结果。
#include <stdio.h> #include <string.h> const int N = 1010; int h, n, Max, s[N], d[N], dist[N]; int now[N], rec[N], vis[N]; void input() { int t; Max = 0; memset(s, 0, sizeof(s)); memset(d, 0, sizeof(d)); memset(dist, 0, sizeof(dist)); memset(rec, 0, sizeof(rec)); scanf("%d", &h); for (int i = 0; i < n; i++) scanf("%d", &s[i]); for (int i = 0; i < n; i++) scanf("%d", &d[i]); for (int i = 1; i < n; i++) { scanf("%d", &dist[i]); dist[i] += dist[i - 1]; } } void output() { if (Max) printf("%d", rec[0] * 5); else printf("%d", h * 60); for (int i = 1; i < n; i++) printf(", %d", rec[i] * 5); printf("\nNumber of fish expected: %d\n", Max); } int find(int m) { int tmp = 0, id; for (int i = 0; i <= m; i++) if (tmp < now[i]) { tmp = now[i]; id = i; } return tmp ? id : -1; } int solve() { int sum, time, id; for (int i = 0; i < n; i++) { time = h * 12 - dist[i]; if (time <= 0) break; memcpy(now, s, sizeof(s)); memset(vis, 0, sizeof(vis)); sum = 0; while (time > 0) { id = find(i); if (id < 0) break; time--; sum += now[id]; now[id] -= d[id]; vis[id]++; } if (time > 0) vis[0] += time; if (sum > Max) { Max = sum; memcpy(rec, vis, sizeof(vis)); } } } int main() { int t, flag = 1; while (scanf("%d", &n) && n) { input(); if (flag) flag = 0; else printf("\n"); solve(); output(); } return 0; }