hzoi 免费馅饼<一般版> 题解

前排提示:

本题解也包含简单版的东西且此题只在hzoj上找到

solve

  • 非常阴的题
  • 由于馅饼下落的时间和速度都不同,⼈只能向左右移动,馅饼只能向下移动。⼈和馅饼都同时移动,思考起来⽐较复杂,因此我们需要转变思路:
  • 算出每个时刻落到最底层的每个格⼦有多少分值的馅饼
  • 如果将馅饼当成参照物,则馅饼向下落,可以看成馅饼不动,⼈往上⾛去摘取馅饼,这样⼈每1时刻都可以⾛到上⼀⾏的5个格⼦,如图
  • 计算出每个格⼦每个时刻可能达到的馅饼分值,填⼊\(W*H\)的天幕表
  • 其中C[i,j]表⽰天幕的第i⾏第j列的馅饼分值,即第i时刻,馅饼落到最底⾏的馅饼分值
  • 设F[i,j]表⽰⼈⾛到第i⾏j列所取得的馅饼最⼤分值和,则有
  • (图白嫖课件的)
  • 有如下要注意的:
    1. 算下落时间时(公式是\((m-1)/c+a\))要特判是否是整数,非整数要干掉不能算
    1. 记录路径要倒序时间,否则你给我预判一下下一时间的决策

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;
}
posted @ 2026-03-22 09:35  msjing  阅读(11)  评论(0)    收藏  举报