一、思考状态转移方程如何写
1、原问题和子问题:
原问题:一个人可以左右移动去接饼,当游戏结束时,接到的饼的最大价值。
子问题:一个人可以左右移动,当到达某一时刻时,接到的饼的最大价值。
可见子问题的求解方式与原问题相同。
2、使子问题是最优解
显然是比较每一个由相同状态转移来的状态,得到最优解就是子问题的最优解。
3、是否无后效性:
解决后效性的最好方法就是增加维度,能把物体的每一个状态的所有要素表现清楚,这题由于子问题求解只需要人的位置和游戏时间,那么维度就是二,要素是位置和时间。
现在就得到了状态转移方程:
sc[i][j]=max(sc[i][j],sc[i+1][j+k]+have[i][j]);
二、需要注意细节:
题目中说当饼在某一秒结束时到达人所在的位置即可,也就是说,饼下落到地面的时间必须是整数。
三、路径打出:
1、循环方法
2、递归方法
#include<bits/stdc++.h>
using namespace std;
int w,h;
const int M=105;
int have[M][M];
int sc[M][M];
int path[M][M];
int mov[4]={1,-1,2,-2};
int main(){
cin>>w>>h;
h--;
int tim,x,v,s;
int maxn=-1;
while(cin>>tim>>x>>v>>s){
if(h%v!=0) continue;
have[tim+h/v][x]+=s;
maxn=max(maxn,tim+h/v);
}
for(int i=maxn;i>=0;i--){
for(int j=1;j<=w;j++){
for(int k=-2;k<=2;k++){
if(j+k>=1&&j+k<=w){
if(sc[i][j]<sc[i+1][j+k]+have[i][j]){
sc[i][j]=sc[i+1][j+k]+have[i][j];
path[i][j]=k;
}
}
}
}
}
cout<<sc[0][(w>>1)+1]<<endl;
int pos=(w>>1)+1;
for(int i=0;i<maxn;i++){
cout<<path[i][pos]<<endl;
pos+=path[i][pos];
}
return 0;
}