动态规划问题,用时间和水平方向的编号作为一个二维的状态。那么某个时间下某个水平编号所能够得到的最大的分数就是由上一个时间段的状态通过5种移动方式得到的。那么状态转移方程就出来了。因为没有涉及到的编号不存在所谓的转移,所以一开始将数组初始化成-1,判断如果等于-1的话直接跳过。
对于路径:同样通过倒索引的方式去一步一步寻找输出。
#include <bits/stdc++.h>
using namespace std;
// #define int long long
struct Oper{
int op;
int par;
} oper[1000+10][100];
struct Node {
int tm;//表示在什么时候到达底部
int pos;//表示水平位置的坐标
int val;//分值
} node[1000+10];
int dp[1000+10][100];
map<int, map<int, int> > mp;
int mv[5] = {-2, -1, 0, 1, 2};
int op_int[5] = {2, 1, 0, -1, -2};
signed main() {
int w, h, n = 0, end_tm=0;
cin>>w>>h;
int t, x, pace, val;
while (cin>>t>>x>>pace>>val) {
if ((h-1)%pace!=0) continue;
n++;
node[n].tm = t+(h-1)/pace;
node[n].pos = x;
node[n].val = val;
mp[x][t+(h-1)/pace] += val;
end_tm = max(end_tm, node[n].tm);
}
memset(dp, -1, sizeof(dp));
dp[0][w/2+1] = 0;
for (int i=1;i<=end_tm;i++) {
for (int j=1;j<=w;j++) {
for (int k=0;k<5;k++) {
int par_j = j+mv[k];
if (par_j>=1&&par_j<=w&&dp[i-1][par_j]!=-1) {
if (dp[i-1][par_j]>dp[i][j]) {
dp[i][j] = dp[i-1][par_j];
oper[i][j].op = op_int[k];
oper[i][j].par = par_j;
}
// dp[i][j] = max(dp[i][j], dp[i-1][par_j]);
}
}
if (mp[j][i]>0) {
dp[i][j] += mp[j][i];
}
}
}
int ans = 0;
int ans_i, ans_j;
for (int j=1;j<=w;j++) {
if (dp[end_tm][j]>ans) {
ans = dp[end_tm][j];
}
// ans = max(ans, dp[end_tm][j]);
}
cout<<ans<<endl;
bool flag = false;
for (int i=1;i<=end_tm;i++) {
for (int j=1;j<=w;j++) {
if (dp[i][j]==ans) {
ans_i = i;
ans_j = j;flag = true;
break;
}
}
if (flag) break;
}
stack<int> st;
while (oper[ans_i][ans_j].par!=0) {
st.push(oper[ans_i][ans_j].op);
ans_j = oper[ans_i][ans_j].par;
ans_i--;
}
while (!st.empty()) {
cout<<st.top()<<endl;
st.pop();
}
return 0;
}

京公网安备 11010502036488号