POJ1402 xingxing在努力
这个题的意思是有n个鱼塘排在一条线上, 一个人刚开始在1号鱼塘, 他现在要从1号鱼塘开始钓鱼, 钓完以后可以去二号但是不能返回一号鱼塘钓鱼, 即只能单向走,从i号鱼塘到i+1号鱼塘需要ti单位时间, 即ti*5分钟的时间,刚开始鱼塘里面有fi条鱼, 钓一次鱼之后鱼的个数会减少di,且钓一次鱼需要5分钟,问如何钓鱼才能使这个人钓的鱼的个数最多, 刚开始看到这道题想到了用贪心, 不过我自己的贪心策略是使单位时间内钓的鱼的个数最多, 然而写出来并过不了样例, 哎太年轻, 原因是我没看清只能单向走这句话, 哭晕在厕所, 完后想了想还是没什么大的进展, 瞄了一眼题解, 上面写着枚举在哪个鱼塘钓鱼, 顿时懂了, 思路大概是这样, 我们枚举从哪个鱼塘里面钓鱼(假设离1号鱼塘最远的鱼塘的编号是e), 然后用总时间减去1-e的时间, 之后我们就认为人可以瞬间从一个鱼塘移动到另外一个鱼塘, 贪心的选取5分钟内所能钓到的鱼的个数最多的那个鱼塘就行了, 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; int n, h, fi[30], di[30], ti[30]; struct lake { int id, num; lake() {} lake(int id, int num):id(id), num(num) {} bool operator< (const lake& r) const { if(num == r.num) return id>r.id; else return num<r.num; } }; int main() { int kase = 0; while(scanf("%d", &n) == 1 && n) { if(kase++) printf("\n"); scanf("%d", &h); for(int i=1; i<=n; i++) scanf("%d", &fi[i]); for(int i=1; i<=n; i++) scanf("%d", &di[i]); ti[0] = 0; for(int i=1; i<n; i++) { int t; scanf("%d", &t); ti[i] = t + ti[i-1]; } int res = -1, ctm[30]; for(int e=1; e<=n; e++) //假设他在1 -> e之间钓鱼 { int ltime = h*60; //剩余时间 ltime -= ti[e-1]*5; if(ltime <= 0) break; //没有剩余时间的时候应该退出 priority_queue<lake> que; for(int i=1; i<=e; i++) que.push(lake(i, fi[i])); int res1 = 0, ctm1[30] = {0}; while(ltime>=5 && !que.empty()) { lake t = que.top(); que.pop(); int id = t.id, num = t.num; ctm1[id]+=5; res1 += num; ltime -= 5; int newnum = num - di[id]; if(newnum < 0 ) newnum = 0; que.push(lake(id, newnum)); } if(res1 > res) { res = res1; memcpy(ctm, ctm1, sizeof(ctm1)); } } for(int i=1; i<n; i++) printf("%d, ", ctm[i]); printf("%d\n", ctm[n]); printf("Number of fish expected: %d\n", res); } return 0; }

浙公网安备 33010602011771号