题解 | #免费馅饼#
免费馅饼
https://ac.nowcoder.com/acm/problem/16850
题意:
一个能向左移动1格或两格,向右能移动1格或两格,也能移动0格的人,在水平宽为W,高度为H的区域内,能接到的馅饼的分值最大为多少。馅饼给出了它掉落的初始时刻、水平位置、掉落速度、分值。
思路:
和数塔类似,把饼落到人高度的时间算出来(人占一格高),然后以时间为横坐标,水平位置为纵坐标,创建一个二维数组,先把馅饼落到人身上的时刻的位置赋上这个馅饼的分数,并且找到落到人身上最后的馅饼的时刻,往0时刻计算,dp[0][W/2]就是最后的答案。状态就是dp[i][j]=下一个时刻他能到达的5个位置里的最大值+dp[i][j]
代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int N=1500;
ll dp[N][N];//表示第i时刻j位置最大的分值是多少
int wzz[N][N];//记录方案
struct Pie{
ll t,x,v,sco,en;
}p[1500];//存馅饼
void print(int x,int y,int maxn)
{
if(x==maxn) return;
if(dp[x+1][y+wzz[x][y]]!=0) cout<<wzz[x][y]<<endl;
print(x+1,y+wzz[x][y],maxn);
}
int main(){
int W,H;
cin>>W>>H;
int n=1;
while(cin>>p[n].t>>p[n].x>>p[n].v>>p[n].sco)
{
if((H-1)%p[n].v || p[n].x>W || p[n].x<1) continue;//判断馅饼是否合法,看一下它的高度是否能被它的速度整除,如果不能,那么它落到的时刻就是个小数,在前一秒做出判断也不知道能不能接到。
p[n].en=(H-1)/p[n].v+p[n].t;//(H-1),人占一格高
n++;
}
ll maxn=0;
n-=1;//n是馅饼数,之前多加了1,减掉1.
//cout<<n<<endl;
for(int i=1;i<=n;i++)
{
maxn=max(p[i].en,maxn);//寻找馅饼掉落到人身上的最晚时间
dp[p[i].en][p[i].x]+=p[i].sco;//在馅饼掉落到人身上的时刻,在馅饼的水平位置上,这个时刻这个位置的最大分值就是接到了这个馅饼,如果从起始位置在馅饼下落时间内接不到也没关系,它从起点到不了这个位置,那么它从这个位置也到不了起点
}
/*for(int i=0;i<=maxn;i++)//可以输出一下刚开始的dp数组看一眼
{
for(int j=1;j<=W;j++)
{
printf("%4d",dp[i][j]);
}
cout<<endl;
}*/
for(int i=maxn-1;i>=0;i--)//maxn-1开始,maxn时刻不用做选择
{
for(int j=1;j<=W;j++)
{
int ans=0;
int wz=0;
//从后往前看所以左右得注意一下
if(j>2 && ans<dp[i+1][j-2]) ans=dp[i+1][j-2],wz=-2;//顺序要从左到右(也没看到题目有说明。。。。),就是判断的顺序是左2步,左1步,0步,右1步,右2步
if(j>1 && ans<dp[i+1][j-1]) ans=dp[i+1][j-1],wz=-1;
if(ans<dp[i+1][j]) wz=0,ans=dp[i+1][j];
if(j<W && ans<dp[i+1][j+1]) ans=dp[i+1][j+1],wz=1;
if(j<W-1 && ans<dp[i+1][j+2]) ans=dp[i+1][j+2],wz=2;
dp[i][j]+=ans;
wzz[i][j]=wz;
}
}
/*for(int i=0;i<=maxn;i++)//可以输出一下处理完的dp数组看一眼
{
for(int j=1;j<=W;j++)
{
printf("%4d",dp[i][j]);
}
cout<<endl;
}*/
/*for(int i=0;i<=maxn;i++)//对应的方案可以看一眼,wzz[i][j]就是记录它下一步要去哪.
{
for(int j=1;j<=W;j++)
{
printf("%4d",wzz[i][j]);
}
cout<<endl;
}*/
//cout<<maxn<<endl;
cout<<dp[0][W/2+1]<<endl;
print(0,W/2+1,maxn);//输出方案
return 0;
}