| |||||
| |||||
|
首先,要认真审题!
对于不管是钓鱼还是行走,都是以5分钟为一个时间单位,所以总时间可以写为H*12;
看到这道题的数据范围与题目,我们不难想到状态转移方程f(i,j)表示前i个鱼塘我花j个时间单位最多可以钓到多少条鱼;
对于这道题来说,现在那个鱼塘钓鱼其实是没有关系的,为什么呢?假如你在第二个鱼塘钓了2个时间单位,在第一个鱼塘钓3个时间单位,最后的时间都可以写成第一个鱼塘钓的时间+走到第二个所需的时间+第二个鱼塘钓鱼的时间,而钓的鱼的数量是第一个鱼塘的加上第二个鱼塘的;
所以当我们在第i个鱼塘,如果可以从第j个时间单位开始钓鱼,那么我们可以从第j个时间单位一直在第i个鱼塘钓到H*12个时间单位;
然而第i个鱼塘的初始状态该怎么设定呢?若第i-1个鱼塘的第j个时间单位可以钓到X条鱼,那么在第i个鱼塘的第j+t[i-1]也可以钓到X条鱼
所以状态转移方程可以写为 先初始第i个鱼塘的值 f(i,j)=f(i-1,j-t[i-1]) (j>=t[i-1])
然后对第i个鱼塘进行状态转移 if(f(i,j)) f(i,j+k)=MAX(f(i,j+k),f(i,j)+p(p代表在第i个鱼塘钓k分钟可以钓多少条鱼)) (j+k<=H*12) //这里的j需要从大往小扫,请想想为什么!
边界f(1,0)=0;
最后答案MAX(f(i,j)) (i<=N j<=H*12)
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int N,H;
int f[30],d[30],t[30];
int p[30][1000];
int g[30];
void Ready()
{
g[1]=0;
scanf("%d%d",&N,&H);
for(int i=1;i<=N;i++)
scanf("%d",&f[i]);
for(int i=1;i<=N;i++)
scanf("%d",&d[i]);
for(int i=1;i<N;i++)
{
scanf("%d",&t[i]);
g[i+1]=g[i]+t[i];
}
memset(p,-1,sizeof(p));
p[0][0]=0;
t[0]=0;
}
int MAX(int x,int y)
{
return x>y?x:y;
}
void Working()
{
int x,y,q;
int tot=H*60/5;
for(int i=1;i<=N;i++)
{
for(int j=0;j<=tot;j++)
{
if(j>=t[i-1])
if(p[i-1][j-t[i-1]]!=-1)
{
p[i][j]=p[i-1][j-t[i-1]];
}
}
for(int r=tot;r>=0;r--)
{
q=f[i];
if(p[i][r]!=-1)
for(int j=1;j<=tot;j++)
{
p[i][r+j]=MAX(p[i][r+j],p[i][r+j-1]+q);
if(q>d[i])q-=d[i];
else q=0;
}
}
}
int ans=-1;
for(int j=1;j<=N;j++)
for(int i=0;i<=tot;i++)
if(ans<p[j][i])ans=p[j][i];
printf("%d",ans);
}
int main()
{
Ready();
Working();
return 0;
}
肯定还有更简单更简洁的方法。。。但我的智商有限。。。
重庆一中 吴松隐