NYOJ 30 && POJ 1042 Gone Fishing(枚举+贪心)
原创
©著作权归作者所有:来自51CTO博客作者herongwei的原创作品,请联系作者获取转载授权,否则将追究法律责任
【题目链接】:Click here~~
【题目大意】:
一个人去钓鱼,在一条单向路上的旁边有n个湖,并且从湖i到湖i+1需要ti的时间,每个湖里面有fi条鱼,每钓一次鱼,鱼会减少di条。在给定时间T内,问如何才能使钓的鱼最多,并记录在各个湖上停留的时间。
【解题思路】
此题细节处理好多麻烦,一定要认真看清题意,POJ WA了无数遍,纠结一天。参考了别人的题解,思路如下:
首先须注意的一点是,John只能向前走,返回的话只会增加John在路上的时间,因而减少他钓鱼的时间。因此此题解题步骤如下:
1、 枚举John经过的最后一个湖,每种情况减去所需步行的时间,剩下的就是钓鱼的时间。
2、 每5分钟选取钓鱼量最多的湖进行钓鱼,直到时间耗尽。
3、 在所有枚举的情况中选择钓鱼量最多的情况,即为问题的最优解。
此题需要注意的几个问题:
1、 如果解不唯一,选择在第一个湖耗时最多的解;如果仍旧存在不惟一解,选择在第二个湖耗时最多的解,以此类推。
2、 随着时间的增加,在某个湖中的钓鱼数可能会出现负数,此时应将该湖中每个时间单位的钓鱼数更新为零。
3、 在测试数据或程序运行的过程中可能出现每个湖鱼数全为0的情况,注意特别处理。
4、 枚举时,结束的标志是剩余时间<=0。
【source】黑书贪心第一题
代码:
#include <stdio.h>
#include <math.h>
#include <queue>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=30;
#define bug puts("AC >_<")
int _time[maxn],ans[maxn],temp[maxn];
struct node
{
int FI,DI;
}Lake[maxn],copyLake[maxn],Dist[maxn];
int main()
{
//freopen("1.txt","r",stdin);
int Lakenum,t,tot=0;
while(cin>>Lakenum&&Lakenum)
{
int Time;
cin>>Time;
Time=Time*60;
for(int i=0; i<Lakenum; i++) cin>>Lake[i].FI; //输入FI
for(int i=0; i<Lakenum; i++) cin>>Dist[i].DI; //输入DI
_time[0]=0;
for(int i=1; i<Lakenum; i++){
cin>>t;
_time[i]=_time[i-1]+t*5; //每个湖的ti
} //每五分钟选取钓鱼量最大的
memset(ans,0,sizeof(ans));
int Max=-1;
for(int i=0; i<Lakenum; i++){ //开始枚举终点的位置{
int sum=0,left_time=Time-_time[i];//总时间-路上消耗时间=该湖钓鱼的时间
memset(temp,0,sizeof(temp));
memcpy(copyLake,Lake,sizeof(Lake));//复制原先初始值
while(left_time>0) //每个湖剩下的能钓鱼的时间,开始捕鱼
{
int maxx=0,id=0;
for(int j=0; j<=i; j++){
if(copyLake[j].FI>maxx){ //第一轮判断哪个湖能捕到最多鱼
maxx=copyLake[j].FI;
id=j;
}
}
if(maxx==0) //时间还剩余,鱼量已经捕完,直接跳出循环
break;
sum+=maxx;
temp[id]+=5;
copyLake[id].FI-=Dist[id].DI;//鱼量依次递减
left_time-=5;
}
if(left_time>0) //时间还剩余!注意加到第一个湖!坑点!
temp[0]+=left_time;
if(sum>Max){ //第二轮判断,所有枚举状态下捕鱼量最大!
Max=sum;
for(int j=0; j<=i; j++)
ans[j]=temp[j];
}
}
if(tot>0) //输出格式
printf("\n");
printf("%d",ans[0]);
for(int i=1; i<Lakenum; i++)
printf(", %d",ans[i]);
printf("\n");
printf("Number of fish expected: %d\n",Max);
tot++;
}
return 0;
}
/*
2
1
10 1
2 5
2
4
4
10 15 20 17
0 3 4 3
1 2 3
4
4
10 15 50 30
0 3 4 3
1 2 3
0
*/