题意:
2 1 10 1 2 5 2意思是有两个湖,有一个小时的时间让你钓鱼
第一个湖泊初始5分钟能钓10个,每过5分钟能钓的鱼减1
第二个湖泊初始5分钟能钓2个,每过5分钟能钓的鱼减5,少于0就是0
从第一个湖泊到第二个湖泊的时间为2*5分钟
你只能在一个湖泊钓鱼,然后走到下一个湖泊,不允许回头
解法:
枚举到达的最后一个湖泊,则已知将会在哪些湖泊钓鱼以及路上花费时间
每次取能获得最大收益的湖泊钓鱼,即为答案
注意:
在收益相同时,在0号湖泊钓的时间长的为最优,若0号相同,则1号,2号。。。
代码:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
class T
{
public:
int f;
int d;
int t;
}lake[30];//0,1,,,,n-1
int n,h;
int num[30];
class U
{
public:
int gains;
int time[30];
}ans;
bool operator>(U a,U b)
{
if(a.gains==b.gains)
{
for(int i=0;i<n;i++)
{
if(a.time[i]==b.time[i])
{
continue;
}
return a.time[i]>b.time[i];
}
}
return a.gains>b.gains;
}
struct cmp
{
bool operator()(int i,int j)
{
int mi=lake[i].f-lake[i].d*num[i];
if(mi<0)
{
mi=0;
}//mi表示在i湖泊钓鱼所得
int mj=lake[j].f-lake[j].d*num[j];
if(mj<0)
{
mj=0;
}
if(mi==mj)//收获相同时序号小优先
{
return i>j;
}
return mi<mj;
}
};
void solve(int m,int h)//0,1,,,m号湖泊
{
int counter=0;
priority_queue<int,vector<int>,cmp>Q;//湖泊序号的优先队列
for(int i=0;i<=m;i++)
{
Q.push(i);
}
for(int i=0;i<=m-1;i++)
{
h-=lake[i].t;
}
while(h>0&&!Q.empty())
{
int tmp=Q.top();//取出当前获得最大值的湖泊序号
Q.pop();
counter+=(lake[tmp].f-num[tmp]*lake[tmp].d)>0?(lake[tmp].f-num[tmp]*lake[tmp].d):0;
num[tmp]++;
h-=5;
Q.push(tmp);
}
if(h>0)
{
num[0]+=h/5;
}
U ant;
for(int i=0;i<=m;i++)
{
ant.time[i]=num[i]*5;
}
for(int i=m+1;i<n;i++)
{
ant.time[i]=0;
}
ant.gains=counter;
if(ant>ans)
{
ans=ant;
}
}
int main()
{
while(scanf("%d",&n),n)
{
ans.gains=-1;
scanf("%d",&h);
h*=60;//换成分钟
for(int i=0;i<n;i++)
{
scanf("%d",&lake[i].f);
}
for(int i=0;i<n;i++)
{
scanf("%d",&lake[i].d);
}
for(int i=0;i<n-1;i++)
{
scanf("%d",&lake[i].t);
lake[i].t*=5;
}
for(int i=0;i<n;i++)//最后到达的是i号湖泊
{
if(i==n-1)
{
i=n-1;
}
memset(num,0,sizeof(num));//每个湖泊已经钓鱼过的次数
solve(i,h);
}
for(int i=0;i<n-1;i++)
{
printf("%d, ",ans.time[i]);
}
printf("%d\n",ans.time[n-1]);
printf("Number of fish expected: %d\n\n",ans.gains);
}
return 0;
}