这个问题比较有韵味,可以好好体会以下!!!
问题描述:
某人想在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;
}