uva757 - Gone Fishing(贪心)

题目:uva757 - Gone Fishing(贪心)

题目大意:有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

uva757 - Gone Fishing(贪心)的相关文章

POJ-1042 Gone Fishing (贪心法求最佳钓鱼方案

Gone Fishing Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 28075   Accepted: 8371 Description John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachab

POJ 1042 Gone Fishing#贪心

(- ̄▽ ̄)-* #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=30; int n,h,H;//H:记录原本有多少小时的时间:h:贪心的时候,防止H被修改 int res[N],RES[N];//res[]:贪心的时候保存结果:RES[]:用于记录最终结果 int maxn,sum;//maxn:保存最终结果,即捕到的鱼最大值:sum:每轮贪心

acm刷题记录

我感觉毫无目的地刷题没有意义,便记录每周的刷题,以此激励自己! ----------6.6-------- [vijos1055]奶牛浴场                                      最大化               推荐IOI论文<浅谈用极大化思想解决最大子矩形问题> codeforces 679B - Bear and Tower of Cubes      xjb搞 codeforces  680A - Bear and Five Cards       

POJ 1042 Gone Fishing (贪心)(刘汝佳黑书)

Gone Fishing Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 30281   Accepted: 9124 Description John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachab

贪心算法 -- gone fishing

poj 1042 gone fishing 题目要求: 由有n个湖, 按照顺序排列,一个人从第一个湖向最后一个湖行进(方向只能从湖0到湖n-1),途中可以在湖中钓鱼.在每个湖中钓鱼时,开始的5分钟内可以钓到 f[i] 条,之后每5分钟钓到的鱼数目递减 d[i] ,且每两个相邻的湖的距离 t[i] 给出(t[i] 表示 由第 i 个湖向第 i + 1个湖行进在路上花费5分钟的倍数的时间, 即如果t[3] = 4,则表示从第三个湖向第四个湖行进需要花费20分钟). 现给定总时间h 小时,求出在每个湖

黑书贪心例题之钓鱼 poj1042:Gone Fishing

总时间限制: 2000ms 内存限制: 65536kB 描述 John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachable along a single, one-way road. John starts at lake 1, but he can finish at a

uva 757 Gone Fishing (贪心)

uva 757 Gone Fishing John is going on a fishing trip. He has h hours available ( ), and there are n lakes in the area ( ) all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel fr

NYOJ 30 &amp;&amp; POJ 1042 Gone Fishing(枚举+贪心)

[题目链接]:Click here~~ [题目大意]: 一个人去钓鱼,在一条单向路上的旁边有n个湖,并且从湖i到湖i+1需要ti的时间,每个湖里面有fi条鱼,每钓一次鱼,鱼会减少di条.在给定时间T内,问如何才能使钓的鱼最多,并记录在各个湖上停留的时间. [解题思路] 此题细节处理好多麻烦,一定要认真看清题意,POJ WA了无数遍,纠结一天.参考了别人的题解,思路如下: 首先须注意的一点是,John只能向前走,返回的话只会增加John在路上的时间,因而减少他钓鱼的时间.因此此题解题步骤如下: 1

Fishing Master HDU - 6709 (贪心)acm

Heard that eomeom is a fishing MASTER, you want to acknowledge him as your mentor. As everybody knows, if you want to be a MASTER's apprentice, you should pass the trial. So when you find fishing MASTER eomeom, the trial is as follow: There are nn fi