問題描述
約翰有h(1≤h≤16)個小時的時間,在該地區有n(2≤n≤25)個湖,這些湖剛好分佈在一條路線上,該路線是單向的。約翰從湖1出發,他可以在任一個湖結束釣魚。但他只能從一個湖到達另一個與之相鄰的湖,而且不必每個湖都停留。
已知在最初5分鐘,湖i預計釣到魚的數量爲fi(fi≥0)。以後每隔5分鐘,預計釣到魚的數量將以常數di(di≥0)遞減。如果某個時段預計釣到魚的數量小於或等於di,那麼在下一時段將釣不到魚。爲簡單起見,假設沒有其它的釣魚者影響約翰的釣魚數量。
問題分析
首先分析問題,在釣魚的過程中,訪問魚塘的順序是單向的,但只能從一個魚塘到相鄰的下一個魚塘,並且從一個魚塘到相鄰的下一個魚塘路程是要耗費時間的。
以5分鐘爲時間週期,每一個時間週期之後魚塘一個週期釣到魚的數量就會減少,即每經過5分鐘,fi就會減少對應的di,直到fi小於等於di時,下一週期便不會釣到魚。
問題的關鍵在於怎麼在各個魚塘上分配時間來釣到更多的魚。給定n之後,即給定魚塘的數量,就可以把釣魚的分爲以下幾個情況,在i(1,2,3,4,5…n)個魚塘結束釣魚進行釣魚,由於釣魚的方向是有向的,我們就可以知道在i個魚塘之間釣魚時,需要花費在路程上的時間,這時我們只需要考慮如何在i個魚塘上分配時間,即每一個週期都選擇fi最大的,看似這種方式好像違背了題目中釣魚方向單向的要求,但並非如此
如圖所示,雖然在算法過程我們先在1,2號魚塘釣完魚之後有返回1號魚塘,但實際的過程則是直接在1號魚塘上進行了兩個週期,然後再進入第二個魚塘進行釣魚,我們的算法只是計算出在各個魚塘中應該垂釣幾次以達到最大釣魚量。這樣依次計算訪問i(1,2,3,4,5…n)個魚塘所產生的最優解最後得到最好的那一個。
代碼
f[30]:表示沒個魚塘初始週期可釣魚數量
d[30]:表示經過一個週期之後f[i]的減少量
plan[30]:表示在每個魚塘耗費的週期數量
t[30]:表示在前往臨近魚塘的時間
best:最多的釣魚數量
void Max(int pos,int time)
{
int f1[30],all=0;
for(int i=0;i<pos;i++)
{
f1[i]=f[i];
}
int p[30];
int max_f;
int idex=0;
memset(p,0,sizeof(p));
while(time>=5)
{for(int i=0;i<pos;i++)
{
max_f=0;
idex=0;
if(f1[i]>max_f)
{
max_f=f1[i];
idex=i;
}
}
if(max_f>0)
{
all+=max_f;
f1[idex]=f1[idex]-d[idex];
time-=5;
p[idex]++;}
else
{
break;
}
}
if(all>best)
{
for(int i=0;i<30;i++)
{
plan[i]=p[i];
}
best=all;
}
}
上述代碼爲了求出在第pos個池塘停止釣魚,純釣魚時間爲time的最多釣魚量
for(int i=0;i<n;i++)
{
int time=h*60;
for(int k=0;k<i;k++)
{
time-=t[k];
}
Max(i+1,time);
}
上述代碼爲了求出在第i個魚塘爲結束位置時,需要耗費的路途時間,從未得到純釣魚時間帶入Max函數中,來求得最大釣魚量。