题意:在一条水平路边,有n(2<=n<=25)个湖,从左到右序号为1,2,3…n。佳佳有H个小时的空余时间,他希望用这些时间钓鱼。他从1号湖出发向右走,有选择地在一些湖边停留一定的时间来钓鱼,最后在某个湖边结束钓鱼。他已测出,从第i个湖到第i+1个湖要走5*Ti分钟的路。他还测出,在第i个湖的第一个5分钟可钓鱼Fi条,以后每5分钟鱼量减少Di。假定没有其他人钓鱼,也不受其他因素影响,编程求出佳佳钓鱼最多的方案。
思路:枚举+贪心
如果直接想的话,不容易想到很好的方法。假设有一种钓鱼方法可以使吊到的鱼数最多,那么中途走路的时间一定是到最远的那个湖的时间。因此,我们只要每次减去到最远的那个湖所走的时间后,我们就可以在里面“瞬移”钓鱼了。因此,枚举第1到第n个湖,提前减去到第n个湖所用的时间,然后每5分钟选取一个鱼量最大的湖钓鱼直到没有鱼或者时间用完为止。
注意:如果鱼量相等,优先输出第一个湖所用时间最多的方案(第一个相等,则第二、三...)
有可能时间还没用完就钓鱼结束了,这时要将剩余的时间加到第一个湖的时间里。
有可能鱼量全部为0或者为负数。
坑爹的数据,话说我是下的官方数据改的代码最后才过的。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n,h,i,j,k,ans,sum;
int ok=1;
int h_need,temp;//h_need为除去走路的时间一共可以钓多久时间的鱼
int f[100],d[100],t[100],time[100];
//freopen("G.in","r",stdin);
//freopen("G.out","w",stdout);
while(scanf("%d",&n)&&n)
{
if(!ok)
printf("\n");
if(ok)
ok=0;
int print_time[100]={0};
sum=0;//sum为实际钓完鱼所用的时间(有可能时间未用完)
memset(time,0,sizeof(time));
int f_tem,h_tem,fish[100];
ans=0;
scanf("%d",&h);//所拥有的时间(小时)
h*=60;
for(i=1;i<=n;i++)
scanf("%d",&f[i]);//最初拥有的鱼
for(i=1;i<=n;i++)
scanf("%d",&d[i]);//每5s所减少的鱼
for(i=1;i<n;i++)
scanf("%d",&t[i]);//每次到另一个鱼塘所需要的时间
h_tem=h,f_tem=f[1];//特判只吊一个鱼池
while(h_tem>0&&f_tem>0)
{
ans+=f_tem;
f_tem-=d[1];
h_tem-=5;
}
print_time[1]=h;
h_need=h;
for(i=2;i<=n;i++)//每次吊前i个鱼塘
{
memset(time,0,sizeof(time));
for(j=1;j<=i;j++)
fish[j]=f[j];
h_tem=h,f_tem=0;
for(j=1;j<i;j++)
h_tem-=(5*t[j]);
temp=h_tem;
while(h_tem>0)
{
int max_fish=fish[1];
int mark=1;
for(j=2;j<=i;j++)//每次找出一个鱼最多的鱼塘
if(fish[j]>max_fish)
{
max_fish=fish[j];
mark=j;
}
if(max_fish<=0)//已经吊完全部的鱼
break;
f_tem+=max_fish;
fish[mark]-=d[mark];
h_tem-=5;
time[mark]+=5;
}
if(ans<f_tem)
{
ans=f_tem;
for(j=1;j<=i;j++)
print_time[j]=time[j];
h_need=temp;
}
else if(ans==f_tem&&ans)
{
for(j=1;j<=i;j++)
{
if(time[j]<print_time[j])
break;
if(time[j]>print_time[j])
{
for(j=1;j<=i;j++)
print_time[j]=time[j];
h_need=temp;
break;
}
}
}
}
for(i=1;i<=n;i++)
sum+=print_time[i];
if(sum!=h_need&&sum<h_need)
print_time[1]+=(h_need-sum);
int ok=0;
for(i=1;i<=n;i++)
if(f[i]>0)
{
ok=1;
break;
}
if(!ok)//特判鱼全部为0或负数(时间全部在第一个鱼池)
{
printf("%d",h);
for(i=2;i<=n;i++)
printf(", 0");
}
else
{
printf("%d",print_time[1]);
for(i=2;i<=n;i++)
printf(", %d",print_time[i]);
}
printf("\n");
printf("Number of fish expected: %d\n",ans);
}
return 0;
}