poj 1042 Gone Fishing
#include<iostream>
using namespace std;
const int iMax = 30;
const int jMax = 200;
/*
首先是贪心的思路:枚举所经过的湖的个数k,每种情况减去所需步行的时间,剩下的就是钓鱼的时间了,
之后就只需要在所剩的时间内使钓鱼数最大,因此每次选择最多鱼的湖点,最后构造起时间段。
*/
/*
解此题的主要方法是枚举+贪心。刚开始的时候还没想到一个好方法,
因为当前鱼最多的池塘是变化的,而题目所给描述里面的钓鱼又是有顺序的,
即:John starts at lake 1, but he can finish at any lake he wants.
He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to.
所以,不可能在池塘中间瞬移,所以贪心貌似不能用。
但转念一想,瞬移还是有可能的,当确定了结束池塘ep(endpond)之后(结束池塘由1枚举到n),
我们便可以把从1到ep的交通费用从h中减去,然后用剩下的时间贪心即可。
因为在分析问题时,对于一个池塘,John在它上面什么时候钓鱼并不重要,所以可以先把John看成很聪明的人,
然后假设他已经知道了在确定了结束池塘后,在每个池塘花多少时间使收益最大(实际上John是在贪心之后才知道的)
,这时我们就可以先减去交通费用,然后在1~ep的池塘中找现在的最大的即可。
*/
#define max(a,b)( a > b ? a : b )
int main(){
int fish[iMax][jMax], decr[iMax], move[iMax];
int LakeNum, Hour,min5, i, j, k;
while(cin >> LakeNum && LakeNum != 0)
{
cin >> Hour;
min5= Hour * 12;
for(i = 1; i <= LakeNum; i ++)
cin >> fish[i][1];
for(i = 1; i <= LakeNum; i ++)
cin >> decr[i];
for(i = 2; i <= LakeNum; i ++)
cin >> move[i];
for(i = 1; i <= LakeNum; i ++)
for(j = 2; j <= min5; j ++)
fish[i][j] = max(fish[i][j-1] - decr[i], 0);
int fishnum = 0, time[iMax];
memset(time, 0, sizeof(time));
time[1] = min5; //考虑全部没有鱼的情况,所有时间耗在time[1]。
for(k = 1; k <= LakeNum; k ++) //枚举所经过的湖数k。
{
int t[iMax], f = 0, count = min5;
memset(t, 0, sizeof(t));
for(i = 2; i <= k; i ++) //注意是从2开始的
count -= move[i];
if(count <= 0) break; // 当总时间不够耗在路程上时,跳出。
while(count --) // 贪心选择count个湖点。
{
int m = 0, p = 1; //p要初始化为1,当下面的for循环没有一次满足条件时,可以优先使t[1]++,保证了下面的要求:
// multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals.
//If there is still a tie, choose the one that spends as long as possible at lake 2, and so on.
for(i = 1; i <= k; i ++)
{
if(fish[i][t[i]+1] > m)
{
m = fish[i][t[i]+1];
p = i;
}
}
f += m;
t[p] ++;
}
if(f > fishnum) //当由于前面的最优解时,构造新的最优解。
{
fishnum = f;
for(i = 1; i <= LakeNum; i ++)
time[i] = t[i];
}
}
for(i = 1; i < LakeNum ; i++)
cout << time[i] * 5 << ", " ; //输出格式也要注意
cout << time[i] * 5 << endl;
cout << "Number of fish expected: " << fishnum << endl << endl;
}
return 0;
}