求解钓鱼问题

这个问题比较有韵味,可以好好体会以下!!!
问题描述:
某人想在h小时内钓到数量最多的鱼。这时他已经在一条路边,从他所在的地方开始,放眼望去,n个湖一字排开,湖编号依次是1.2…n。他已经知道,从湖i走到湖i+1需要花5*ti分钟;他在湖i钓鱼,第一个5分钟可钓到数量为fi的鱼,若他继续在湖i钓鱼,每过5分钟,钓鱼量将减少di。
请给他设计一个最佳钓鱼方案。
解决思想:

解决思想有一些贪心的思想,但主要还是暴力枚举
用Lake[i]记录以第 i 个湖结尾的方案,
Lake中为结构体,记录以此方案结尾所能获得的最大鱼数目:max,
以及用num[i]记录从1~i钓鱼,所待的时间
中心思想:先假设从湖1走到湖i,在这个前提下计算出在湖k所待的时间,然后在此基础上求解最大钓鱼数目

代码中有非常详细的注释!!!

样例:

2
1
输入相邻移动花费的时间:2
初始每个湖鱼的个数:10 1
一个时间间隔,鱼减少的个数:2 5

最佳方案:
钓鱼总数目:31
        第1个湖,钓鱼停留时间:45
        第2个湖,钓鱼停留时间:5

代码:

#include<bits/stdc++.h>
using namespace std;
#define MAX 20 

int n;	//湖的个数 
int h;	//	时间 
int max_values=0;	//记录活得最大鱼的数目 的方案,是以角标i结尾的 

int ti[MAX];	//i~i+1花费时间 
int fi[MAX];	//初始每个湖鱼个数
int cfi[MAX];	//记录更新后每个湖鱼的个数
int di[MAX];	//间隔五分钟,鱼减少的数目 

//记录方案 ——以i结尾的湖_方案 
struct NodeType{
	int num[MAX];	//每个湖停留时间 
	int max;	//最大钓鱼数目 
}Lake[MAX];

//得到最大角标
int getMax(int a[],int i,int j){
	int max_index=i;
	for(i=i;i<=j;i++){
		if(cfi[i]>cfi[max_index]){
			max_index=i;
		}
	} 
	return max_index;
} 

//求解方案函数 
void solve(){
	
	int T=60*h;
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cfi[j]=fi[j];	//初始化
			//去除在路上的时间 
			if(j<i){
				T=T-5*ti[j];
			}			
		}
		
		int t=0;
		
		//其余时间用来钓鱼 
		while(t<T){
			int t_index=getMax(cfi,1,i);
			Lake[i].max+=cfi[t_index];	//记录以i结尾所钓鱼数目的最大值 
			Lake[i].num[t_index]+=5;	//在角标为t_index的湖,钓鱼时间加上一个周期5
			
			//判断此湖鱼的数量
			if(cfi[t_index]>=di[t_index]){
				cfi[t_index]-=di[t_index];
			}
			else{
				cfi[t_index]=0;
			}
			t+=5;	
		}	
			
	}
	
} 

//主函数 
int main(){
	cin>>n;
	cin>>h;
	
	//初始化
	for(int i=1;i<=n;i++){
		Lake[i].max=0;
		for(int j=1;j<=n;j++){
			Lake[i].num[j]=0;
		}
	} 
	
	cout<<"输入相邻移动花费的时间:";
	for(int i=1;i<n;i++){
		cin>>ti[i];
	} 
	
	cout<<"初始每个湖鱼的个数:";
	for(int i=1;i<=n;i++){
		cin>>fi[i];
	} 
	
	cout<<"一个时间间隔,鱼减少的个数:";
	for(int i=1;i<=n;i++){
		cin>>di[i];
	} 
	
	//调用求解函数
	 solve();
	
	//打印 
	cout<<"最佳方案:"<<endl;
	for(int i=1;i<=n;i++){
		if(Lake[i].max>Lake[max_values].max){
			max_values=i;
		}
	} 
	cout<<"钓鱼总数目:"<<Lake[max_values].max<<endl;	
	//输出每个湖所钓分钟数目 
	for(int i=1;i<=n;i++){
		if(Lake[max_values].num[i]!=0){
			cout<<"	第"<<i<<"个湖,钓鱼停留时间:"<<Lake[max_values].num[i]<<endl;
		} 
	}
	
	return 0;
} 
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值