説明
ジョンは釣り旅行に行きます。彼はh時間利用可能であり(1 <= h <= 16)、この地域にはn個の湖(2 <= n <= 25)があり、すべて一方通行の単一道路に沿って到達できます。ジョンは湖1から始めますが、好きな湖で終わることができます。彼はある湖から次の湖へしか移動できませんが、希望しない限り、どの湖にも立ち寄る必要はありません。各i = 1、…、n-1について、i湖からi +1湖まで移動するのにかかる5分間隔の数はti(0 <ti <= 192)で表されます。たとえば、t3 = 4は、湖3から湖4までの移動に20分かかることを意味します。釣り旅行の計画を立てるために、ジョンは湖に関するいくつかの情報を収集しました。各湖iについて、fi(fi> = 0)で表される最初の5分間に捕獲されると予想される魚の数がわかっています。5分間の釣りごとに、次の5分間隔で捕獲されると予想される魚の数が一定の割合で減少します(di> = 0)。ある間隔で捕獲されると予想される魚の数がdi以下の場合、次の間隔で湖に残っている魚はなくなります。計画を簡素化するために、ジョンは、彼が捕まえると予想する魚の数に影響を与えるために、他の誰も湖で釣りをしないと想定しています。
ジョンが釣りに行く計画を立てて、釣れると予想される魚の数を最大化するのに役立つプログラムを作成します。各湖で過ごす分数は5の倍数でなければなりません。
入力
入力にはいくつかのケースがあります。各ケースは、nを含む行で始まります。この後にhを含む行が続きます。次に、fi(1 <= i <= n)を指定するn個の整数の行、次にn個の整数di(1 <= i <= n)の行、最後にn-1個の整数ti( 1 <= i <= n-1)。n = 0の場合で入力が終了します。
出力
テストケースごとに、各湖で過ごした分数をコンマで区切って印刷し、予想される最大の魚の数を達成する計画を立てます(80文字を超えても、計画全体を1行に印刷する必要があります)。この後に、予想される魚の数を含む行が続きます。
複数の計画が存在する場合は、一定の間隔で魚が釣れないと予想される場合でも、湖1でできるだけ長く過ごす計画を選択してください。それでも同点の場合は、2湖でできるだけ長く過ごすものを選択します。ケースの間に空白行を挿入します。
サンプル入力
2
1
10 1
2 5
2
4
4
10 15 20 17
0 3 4 3
1 2 3
4
4
10 15 50 30
0 3 4 3
1 2 3
0
サンプル出力
45、5
魚の数は予想:31
240、0、0、0
予想される魚の数:480
115、10、50、35
予想される魚の数:724
アイデア
結局、異なる位置に行くのに異なる時間がかかり、以下の位置でより多くの魚が得られる可能性があります。すべてがすべての終了位置を列挙します。最初に合計時間を使用して、終点の前に各位置で費やされた時間を差し引き、残りは釣りに使用できる時間です。湖の数と、現在の単位時間に湖で捕獲できる魚の数を、魚の数でソートされた優先キューに追加します。釣り時間が合計時間に達していない場合、キューの最初の要素が取り出されるたびに、魚の数が累積され、各養魚池の釣り時間配列の対応する値に1が加算され、湖での継続的な吊り下げが更新され、のキューに追加されます。時間がなくなるまで循環します。最後に、釣りの総数を比較します。前の回答よりも多い場合は、更新します。
コード
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int f[30]; //第一个单位时间钓到的鱼的数量
int d[30]; //后面每次减少的数量
int t[30]; //从第i-1个鱼塘到第i个鱼塘的时间
int maxlaketime[30]; //钓鱼总数最大时,在每个鱼塘停留的时间
int nowlaketime[30]; //枚举过程中,在每个鱼塘停留的时间
struct lake //lake对应的是一个鱼塘状态 同一个鱼塘不同时间钓到不同数量的鱼
{
int i,n; //i 鱼塘编号 n 当前在该鱼塘可钓到的鱼的数量
friend bool operator < (const lake a,const lake b)
{
if(a.n==b.n)
return a.i>b.i; //按当前状态钓到的鱼数从大到小排序
return a.n<b.n; //相等则按序号排
}
};
int main()
{
int n;
while(1)
{
cin>>n;
if(n==0)
return 0;
int h;
cin>>h;
for(int i=1;i<=n;i++)
cin>>f[i];
for(int i=1;i<=n;i++)
cin>>d[i];
for(int i=2;i<=n;i++)
cin>>t[i];
int maxfish=-1;
for(int i=1;i<=n;i++) //枚举终点位置
{
int nowfish=0; //重置数据
memset(nowlaketime,0,sizeof(nowlaketime));
int fishtime=h*12; //时间转换
for(int j=2;j<=i;j++)
fishtime-=t[j]; //减去路上的时间
priority_queue<lake>q; //优先队列
for(int j=1;j<=i;j++)
{
lake tmp;
tmp.i=j;
tmp.n=f[j];
q.push(tmp); //将鱼塘的初始状态加入队列
}
for(int j=1;j<=fishtime;j++)
{
lake tmp=q.top(); //首元素
q.pop();
nowlaketime[tmp.i]++; //对应鱼塘的时间加1
nowfish+=tmp.n; //累计鱼的数量
tmp.n-=d[tmp.i]; //该鱼塘状态更新
if(tmp.n<0)
tmp.n=0; //小于0
q.push(tmp); //重新加入队列
}
if(nowfish>maxfish) //大于答案,更新答案
{
maxfish=nowfish;
memcpy(maxlaketime,nowlaketime,sizeof(nowlaketime));
}
if(nowfish==maxfish) //相等,则比较顺序
{
for(int j=1;j<=n;j++)
if(maxlaketime[j]<nowlaketime[j])
{
memcpy(maxlaketime,nowlaketime,sizeof(nowlaketime));
break;
}
else if(maxlaketime[j]>nowlaketime[j])
break;
}
}
for(int i=1;i<n;i++) //按格式输出
cout<<maxlaketime[i]*5<<", ";
cout<<maxlaketime[n]*5<<endl;
cout<<"Number of fish expected: "<<maxfish<<endl<<endl; // 注意两个换行
}
}