第八第九,还有subtask三个点WA 样例+讨论版hack数据全过,代码下面另附的两组数据也过了
#include <cmath>
#include <iostream>
#include <vector>
#include <algorithm>
#include <array>
using namespace std;
struct brick {
int score;
bool contains_bullet;
};
//滚动数组,在线算法
int main() {
size_t n, m, k;
cin >> n >> m >> k;
vector<array<int, 2> > prev_dp(k + 1); //之前的dp结果, prev_dp[i][j]代表截至上一行为止,用i颗子弹能获取的最大分数(其中j == 1代表返还一个子弹,j == 0代表不返还)
vector mp(m, vector<brick>(n));
//倒序输入
for (size_t i = n - 1; ; --i) {
for (size_t j = 0; j < m; ++j) {
char c;
cin >> mp[j][i].score >> c;
mp[j][i].contains_bullet = c == 'Y';
}
if (!i)
break;
}
for (size_t i = 0; i < n; ++i) {
vector<brick> cur{move(mp[i])};
//便输入边算,在线算法,输入完了结果也同步算出来了
vector<array<int, 2> > cur_bu_to_score({{0, 0}, {0, 0}});
//cur_bu_to_score[i][j]代表当前弹道有index的子弹时能够获得的最大分数(一弹一段表),其中j == 1时要求返还子弹(若不可能则用0表示)
cur_bu_to_score.reserve(m + 2); //合法的子弹数量是从0到k,一共k+1项,而下面的算法会溢出一项,所以额外+1
for (auto [s, c]: cur) {
auto &b = cur_bu_to_score.back();
b[0] += s;
if (c) {
b[1] = b[0];
} else
cur_bu_to_score.push_back({b[0], 0});
}
if (!cur_bu_to_score.back()[1]) //若最后一项不给子弹,上面的算法会多插入一项,这里弹一下
cur_bu_to_score.pop_back();
// fixme 最后一块砖里有子弹的情况
vector<array<int, 2> > cur_dp(k + 1);
//用j遍历每一个可能的(在所有列中一共的)可用的子弹数量
for (size_t j = 0; j <= k; ++j) {
//l代表分给新的一列多少子弹
for (size_t l = 0; l <= min(j, cur_bu_to_score.size() - 1); ++l) {
//生成新一列的dp结果
//这里只拿到l个子弹,而可用的子弹数为j,意味着前面已经用掉j-l颗子弹了
cur_dp[j][0] = max({
true ? cur_dp[j][0] : 0,
true ? prev_dp[j - l][0] + cur_bu_to_score[l][0] : 0,
prev_dp[j - l][1] && l < min(j, cur_bu_to_score.size() - 1) ? prev_dp[j - l][1] + cur_bu_to_score[l + 1][0] : 0,
cur_bu_to_score[l][1] && l ? prev_dp[j - l + 1][0] + cur_bu_to_score[l][1] : 0,
});
cur_dp[j][1] = max({
true ? cur_dp[j][1] : 0,
prev_dp[j - l][1] ? prev_dp[j - l][1] + cur_bu_to_score[l][0] : 0,
cur_bu_to_score[l][1] ? prev_dp[j - l][0] + cur_bu_to_score[l][1] : 0,
prev_dp[j - l][1] && cur_bu_to_score[l][1] && l < min(j, cur_bu_to_score.size() - 1) ? prev_dp[j - l][1] + cur_bu_to_score[l + 1][1] : 0,
prev_dp[j - l][1] && cur_bu_to_score[l][1] && l ? prev_dp[j - l + 1][1] + cur_bu_to_score[l][1] : 0,
});
}
}
prev_dp = move(cur_dp); //滚动数组,节省空间
}
cout << prev_dp[k][0];
}
/*
3 3 3
1 N 1 N 1 N
1 N 1 Y 1 Y
3 Y 3 N 1 Y
1 2 1
1 N 1 N
*/