#include<iostream>
#include<memory.h>
using namespace std;
const int MAX = 25;
void ComputeFish(int n, int h, int *f, int *d, int *t);
class Lake{
public:
int fi; //Fish number at start
int di; //Decrese Rate
int index; //Lake index;
void Set(int fi, int di, int index);
};
bool CmpLake(Lake &a, Lake &b);
void SwapLake(Lake &a, Lake &b);
class Heap{
private:
Lake *lakes;
int size;
void Adjust(int i);
public:
Heap(Lake* a, int size); //We use size, not end index
void BuildHeap();
Lake GetMax(); //Heap will automatically decrese max.fi by max.di
};
int main() {
//get the input
int n, h;
int f[MAX], d[MAX], t[MAX - 1];
do {
cin>>n>>h;
for(int i = 0 ; i < n; i++) cin>>f[i];
for(int i = 0; i < n; i++) cin>>d[i];
for(int i = 0; i < n - 1; i++) cin>>t[i];
//Compute
if(n != 0) ComputeFish(n, h, f, d, t);
}while(n != 0);
}
void ComputeFish(int n, int h, int *f, int *d, int *t) {
//We must enumerate where to end
Lake lakes[MAX];
int bestNum, curNum;
int bestPlan[MAX], curPlan[MAX];
bestNum = -1;
memset(bestPlan, 0, MAX * sizeof(int));
for(int endLake = 0; endLake < n; endLake++) {
//init
curNum = 0;
memset(curPlan, 0, MAX * sizeof(int));
//We end at endLake, ranges [0, n - 1]
for(int i = 0; i <= endLake; i++) lakes[i].Set(f[i], d[i], i);
//Use this to create a heap
Heap a(lakes, endLake + 1);
//Compute how many times we can fish
int walktime = 0;
for(int i = 0; i < endLake; i++) walktime += t[i] * 5;
int fishtime = h * 60 - walktime;
int times = fishtime / 5;
for(int i = 0; i < times; i++) {
Lake ret = a.GetMax();
if(ret.fi == 0) {
curPlan[ret.index] += times - i;//?
break;
}
curNum += ret.fi;
curPlan[ret.index]++;
}
if(bestNum < curNum) { //Do we need to consider bestNum == curNum??
memcpy(bestPlan, curPlan, sizeof(int) * (endLake + 1));
bestNum = curNum;
}
}
for(int i = 0; i < n - 1; i++) cout<<(bestPlan[i] * 5)<<", ";
cout<<bestPlan[n - 1] * 5<<endl;
cout<<"Number of fish expected: "<<bestNum<<endl<<endl;
}
void Lake::Set(int fi, int di, int index) {
this->fi = fi;
this->di = di;
this->index = index;
}
bool CmpLake(Lake &a, Lake &b) {
return a.fi > b.fi || (a.fi == b.fi && a.index < b.index);
}
void SwapLake(Lake &a, Lake &b) { //I hope it works!
Lake temp = b;
b = a;
a = temp;
}
void Heap::Adjust(int i) {
int max = i;
while(true) {
int left = 2 * i + 1;
int right = 2 * i + 2;
if(left < size && CmpLake(lakes[left], lakes[max])) max = left;
if(right < size && CmpLake(lakes[right], lakes[max])) max = right;
if(max != i) {
SwapLake(lakes[max], lakes[i]);
i = max;
}else break;
}
}
void Heap::BuildHeap() {
int median = (size - 2) / 2;
for(int i = median; i >= 0; i--) Adjust(i);
}
Heap::Heap(Lake *a, int size) {
this->lakes = a;
this->size = size;
BuildHeap();
}
Lake Heap::GetMax() {
Lake ret = lakes[0];
if(lakes[0].fi > lakes[0].di) lakes[0].fi -= lakes[0].di;
else lakes[0].fi = 0;
Adjust(0); //Forgetting this line will incur a serious error
return ret;
}
这道题WA了3次:
1. 如果钓鱼钓到某个时间了, 那么每个湖都没有鱼的情形,应该呆在第一个湖;这段时间必须算进去
2. 考虑到 其实钓到的鱼的最小数目是0。 所以说bestNum一开始置为0是很愚蠢的做法。 应该置为-1.