hzoi 免费馅饼<一般版> 题解
前排提示:
本题解也包含简单版的东西且此题只在hzoj上找到
solve
非常阴的题- 由于馅饼下落的时间和速度都不同,⼈只能向左右移动,馅饼只能向下移动。⼈和馅饼都同时移动,思考起来⽐较复杂,因此我们需要转变思路:
- 算出每个时刻落到最底层的每个格⼦有多少分值的馅饼
- 如果将馅饼当成参照物,则馅饼向下落,可以看成馅饼不动,⼈往上⾛去摘取馅饼,这样⼈每1时刻都可以⾛到上⼀⾏的5个格⼦,如图

- 计算出每个格⼦每个时刻可能达到的馅饼分值,填⼊\(W*H\)的天幕表
- 其中C[i,j]表⽰天幕的第i⾏第j列的馅饼分值,即第i时刻,馅饼落到最底⾏的馅饼分值
- 设F[i,j]表⽰⼈⾛到第i⾏j列所取得的馅饼最⼤分值和,则有
(图白嫖课件的)- 有如下要注意的:
-
- 算下落时间时(公式是\((m-1)/c+a\))要特判是否是整数,非整数要干掉不能算
-
- 记录路径要倒序时间,否则你给我预判一下下一时间的决策
Code简单版
#include<bits/stdc++.h>
using namespace std;
int n,m;
int w[100100];
int g[101][110];
int cnt;
int timee;
int dp[10010][110];
int path[10010][110];
int main()
{
memset(dp,-0x3f,sizeof(dp));
cin >> n >> m;
int a,b,c,d;
while (cin >> a >> b >> c >> d)
{
if ((m-1)%c!=0) continue;
g[(m-1)/c+a][b]+=d;
timee=max(timee,(m-1)/c+a);
}
dp[0][n/2+1]=0;
for (int i=1;i<=timee;i++)
{
for (int j=1;j<=n;j++)
{
// dp[i][j]=mymax(dp[i+1][max(j-2,0)],
// dp[i+1][j-1],
// dp[i+1][j],
// dp[i+1][j+1],
// dp[i+1][j+2])
// +g[i][j];
if (j-2>=1)
{
dp[i][j]=dp[i-1][j-2]+g[i][j];
// path[i][j]=2;
}
if (j-1>=1 && dp[i][j]<dp[i-1][j-1]+g[i][j])
{
dp[i][j]=dp[i-1][j-1]+g[i][j];
// path[i][j]=1;
}
if (dp[i][j]<dp[i-1][j]+g[i][j])
{
dp[i][j]=dp[i-1][j]+g[i][j];
// path[i][j]=0;
}
if (j+1<=n && dp[i][j]<dp[i-1][j+1]+g[i][j])
{
dp[i][j]=dp[i-1][j+1]+g[i][j];
// path[i][j]=-1;
}
if (j+2<=n && dp[i][j]<dp[i-1][j+2]+g[i][j])
{
dp[i][j]=dp[i-1][j+2]+g[i][j];
// path[i][j]=-2;
}
}
}
int ans=0;
for (int i=1;i<=n;i++) ans=max(ans,dp[timee][i]);
cout << ans << endl;
return 0;
}
Code一般版
#include<bits/stdc++.h>
using namespace std;
int n,m;
int w[100100];
int g[101][110];
int cnt;
int timee;
int dp[10010][110];
int path[10010][110];
int p[100010];
void Path(int t,int x)
{
if (t == timee) return;
p[t+1]=path[t][x]-x;
Path(t+1,path[t][x]);
}
int main()
{
memset(dp,-0x3f,sizeof(dp));
cin >> n >> m;
int a,b,c,d;
while (cin >> a >> b >> c >> d)
{
if ((m-1)%c!=0) continue;
g[(m-1)/c+a][b]+=d;
timee=max(timee,(m-1)/c+a);
}
for (int i=1;i<=n;i++) dp[timee][i]=g[timee][i];
for (int i=timee-1;i>=0;i--)
{
for (int j=1;j<=n;j++)
{
if (j-2>=1 && dp[i][j]<dp[i+1][j-2]+g[i][j])
{
dp[i][j]=dp[i+1][j-2]+g[i][j];
path[i][j]=j-2;
}
if (j-1>=1 && dp[i][j]<dp[i+1][j-1]+g[i][j])
{
dp[i][j]=dp[i+1][j-1]+g[i][j];
path[i][j]=j-1;
}
if (dp[i][j]<dp[i+1][j]+g[i][j])
{
dp[i][j]=dp[i+1][j]+g[i][j];
path[i][j]=j;
}
if (j+1<=n && dp[i][j]<dp[i+1][j+1]+g[i][j])
{
dp[i][j]=dp[i+1][j+1]+g[i][j];
path[i][j]=j+1;
}
if (j+2<=n && dp[i][j]<dp[i+1][j+2]+g[i][j])
{
dp[i][j]=dp[i+1][j+2]+g[i][j];
path[i][j]=j+2;
}
}
}
cout << dp[0][n/2+1] << endl;
Path(0,n/2+1);
for (int i=1;i<=timee;i++) cout << p[i] << endl;
return 0;
}

浙公网安备 33010602011771号