poj-1042 Gone Fishing **

/*  贪心+优先级队列
*
* 贪心:为了不讨论在路上花费的时间,可以枚举到过的湖:比如:totLake=j 表示 到过湖1、2、..、j 相应的, 花在路上的时间
* 就是 t[1]+t[2]+..+t[j-1] (显然每段路只会走一次) 于是算出leftTime,表示花在钓鱼上的时间
* 这样一来,就不同再考虑路上的时间了,可以认为John有瞬间移动,哪个湖鱼多,就到哪个湖钓(当然 湖的编号 满足 1 <= ~ <=totLake )
*
* 于是可以用一个优先级队列,每次到与最多的湖钓,
* 还要注意的是,如果某时刻有多个湖有同样多的鱼,则到湖编号最小的那个湖里钓!!(只要对优先级队列做相应的修改)
* 用二叉堆实现优先级队列
*
* 最后注意ans == 0的情况
* 看数据:
* 2
* 1
* 0 0
* 1 1
* 1
* 答案:
* 60 0
* 0
*/

#include
<cstdio>
#include
<cstring>
using namespace std;

const int maxN = 25 + 2, inf = 100000;
int n, h, f[maxN], d[maxN], t[maxN]; //如题所述
int timeOnLake[maxN], totLake, ans, ansTimeOnLake[maxN];

int heap[maxN], key[maxN]; //heap【】:该节点的湖编号。。key【】:该节点当前的能钓到的鱼数


void ini(){
for(int i=1; i<=totLake; i++){
heap[i]
= i; key[i] = f[i];
}
memset(timeOnLake,
0, sizeof(timeOnLake));
}

int inline left(int i){ return i*2; }
int inline right(int i){ return i*2+1; }
int inline p(int i){ return i/2; }

void inline swap(int x, int y){
int tmp;
tmp
= heap[x]; heap[x] = heap[y]; heap[y] = tmp;
tmp
= key[x]; key[x] = key[y]; key[y] = tmp;
}

void max_heapify(int i, int tot){
int imax = i;
int l = left(i);
int r = right(i);

//注意做相应的修改。。key相同时,湖编号小的优先级高
if(l <= tot && (key[l] > key[imax] || (key[l]==key[imax] && heap[l] < heap[imax])))
imax
= l;
if(r <= tot && (key[r] > key[imax] || (key[r]==key[imax] && heap[r] < heap[imax])))
imax
= r;

if(imax != i){
swap(i, imax);
max_heapify(imax, tot);
}
}
//建堆
void build_max_heap(){
for(int i=totLake/2; i>=1; i--){
max_heapify(i, totLake);
}
}
//弹出最大元
int heap_extract_max(int &lakeNum, int &tot){
lakeNum
= heap[1];
int maxKey = key[1];

swap(
1, tot);
tot
--;
max_heapify(
1, tot);
return maxKey;
}
//把i节点的key增加到newKey
void heap_increase_key(int i, int newKey){
key[i]
= newKey;
//注意这里也要有相应的修改
while(i>1 && (key[p(i)]<key[i] || (key[p(i)]==key[i] && heap[p(i)]>heap[i]))){
swap(i, p(i));
i
= p(i);
}
}
//插入key为newKey的节点
void max_heap_insert(int newNode, int &tot){
tot
++;
key[tot]
= -inf;
heap_increase_key(tot, newNode);
}

//函数
void fish(int timeLeft){
build_max_heap();

int tmp_ans = 0;
while(timeLeft){
int lakeNum, tot = totLake;
int maxFish = heap_extract_max(lakeNum, tot);

if(maxFish == 0){ //没鱼可钓了,直接在1号湖加上timeLeft
timeOnLake[1] += timeLeft; break;
}

tmp_ans
+= maxFish;
timeOnLake[lakeNum]
++;

int newfish = (maxFish-d[lakeNum]<0 ? 0 : maxFish-d[lakeNum]);
max_heap_insert(newfish, tot);

timeLeft
--;
}

if(tmp_ans > ans){
ans
= tmp_ans;
memcpy(ansTimeOnLake, timeOnLake,
sizeof(ansTimeOnLake));
}
}



int main(){
while(scanf("%d", &n)){
if(n == 0)
return 0;

scanf(
"%d", &h);
h
= h * 60 / 5; //改为以5分钟为单位
for(int i=1; i<=n; i++)
scanf(
"%d", &f[i]);
for(int i=1; i<=n; i++)
scanf(
"%d", &d[i]);
for(int i=1; i<n; i++)
scanf(
"%d", &t[i]);
t[
0] = 0;


ans
= 0;
int timeOnRoad = 0;
for(totLake=1; totLake<=n; totLake++){
timeOnRoad
+= t[totLake-1];
if(timeOnRoad > h) break;

ini();
int timeLeft = h - timeOnRoad;
fish(timeLeft);
}

//注意ans==0的情况!!
if(ans == 0){
printf(
"%d", h*5);
for(int i=2; i<=n; i++)
printf(
", %d", 0);
printf(
"\nNumber of fish expected: %d\n\n", ans);
}
else{
for(int i=1; i<n; i++)
printf(
"%d, ", ansTimeOnLake[i]*5);
printf(
"%d\n", ansTimeOnLake[n]*5);
printf(
"Number of fish expected: %d\n\n", ans);
}
}

return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值