题意:
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; }