ybt1373 鱼塘钓鱼

版权声明:本文为博主原创文章,未经博主允许不得转载,不得用于商业用途。 https://blog.csdn.net/WDAJSNHC/article/details/82533776

ybt1373 鱼塘钓鱼

时空限制    1000ms/64MB

【题目描述】

有N个鱼塘排成一排(N<100),每个鱼塘中有一定数量的鱼,例如:N=5时,如下表:

即:在第1个鱼塘中钓鱼第1分钟内可钓到10条鱼,第2分钟内只能钓到8条鱼,……,第5分钟以后再也钓不到鱼了。从第1个鱼塘到第2个鱼塘需要3分钟,从第2个鱼塘到第3个鱼塘需要5分钟,……

给出一个截止时间T(T<1000),设计一个钓鱼方案,从第1个鱼塘出发,希望能钓到最多的鱼。

假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。

【输入】

共5行,分别表示:

第1行为N;

第2行为第1分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;

第3行为每过1分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;

第4行为当前鱼塘到下一个相邻鱼塘需要的时间;

第5行为截止时间T。

【输出】

一个整数(不超过231−1

),表示你的方案能钓到的最多的鱼。

【输入样例】

5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14

【输出样例】

76

代码

法一:贪心

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 105;
int n,f[N],d[N],t[N],T;
int a[N],ans;

int main(){
	cin>>n;
	for (int i=1; i<=n; i++) cin>>f[i];
	for (int i=1; i<=n; i++) cin>>d[i];
	for (int i=1; i<n; i++) cin>>t[i];
	cin>>T;
	for (int i=1; i<=n; i++){	//枚举终点鱼塘
		for (int j=1; j<=i; j++) a[j]=f[j];	//初始化
		T -= t[i-1];	// T 鱼塘1-i所剩钓鱼时间
		int tot=0;
		for (int j=1; j<=T; j++){
			int pos=0;
			for (int k=1; k<=i; k++)	//每次钓鱼在哪个鱼塘
				if (a[k]>a[pos]) pos=k;
			if (pos==0) break;	//所有鱼塘都钓不了鱼
			tot += a[pos];	//累加本次钓鱼数
			a[pos] -= d[pos];	//本次鱼塘下次钓鱼数
		}
		ans = max(ans,tot);
	}
	cout<<ans<<endl;
	return 0;
}

法二:STL优先队列

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 105;
struct node{
    int fish,id;
    bool operator < (const node &x)const{
        return fish<x.fish;	//重载 < 成大根堆
    }
}f[N];
priority_queue<node> pq;
int n,d[N],t[N],T,ans;

int main(){
    cin>>n;
    for (int i=1; i<=n; i++){
        cin>>f[i].fish;
        f[i].id=i;	//鱼塘编号
    }
    for (int i=1; i<=n; i++) cin>>d[i];
    for (int i=1; i<n; i++) cin>>t[i];
    cin>>T;
    for (int i=1; i<=n; i++){	//枚举终点鱼塘
        while (!pq.empty()) pq.pop();	//清空堆
        for (int j=1; j<=i; j++) pq.push(f[j]);	//建大顶堆
        T -= t[i-1];	// T 鱼塘1-i所剩钓鱼时间
        int tot=0;
        for (int j=1; j<=T; j++){
            node x=pq.top(); pq.pop();	//取出最大值
            if (x.fish<=0) break;
			tot+=x.fish;	//累加本次钓鱼数
            x.fish -= d[x.id];	//本次鱼塘下次钓鱼数
            pq.push(x);	//重新入堆
        }
        ans = max(ans,tot);
    }
    cout<<ans<<endl;
    return 0;
}

法三:手动堆

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 105;
struct node{
	int fish,id;
}heap[N];
int n,f[N],d[N],t[N],T,ans;

void adjust(int i,int m){
	for (int j=2*i; j<=m; ){
		if (j<m && heap[j+1].fish>heap[j].fish) j++;	//存在右孩子且值大
		if (heap[i].fish<heap[j].fish){	//heap[i]父亲节点 heap[j]孩子节点
			swap(heap[i],heap[j]);
			i = j;
			j = 2*i;
		}
		else break;
	}
}

int main(){
	cin>>n;
	for (int i=1; i<=n; i++) cin>>f[i];
	for (int i=1; i<=n; i++) cin>>d[i];
	for (int i=1; i<n; i++) cin>>t[i];
	cin>>T;
	for (int i=1; i<=n; i++){	//枚举终点鱼塘
		for (int j=1; j<=i; j++){	//建立大顶推
			heap[j].fish = f[j];
			heap[j].id = j;
		}
		for (int j=i/2; j>=1; j--) adjust(j,i);
		T -= t[i-1];	// T 鱼塘1-i所剩钓鱼时间
		int tot=0;
		for (int j=1; j<=T; j++){
			if (heap[1].fish<=0) break;
			tot += heap[1].fish;	//累加本次钓鱼数
			heap[1].fish -= d[heap[1].id];	//本次鱼塘下次钓鱼数
			adjust(1,i);	//向下调整
		}
		ans = max(ans,tot);
	}
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/WDAJSNHC/article/details/82533776