社区讨论
问了一下ai, 没有提交, 也不敢提交, 只是想看一下有没有正解。
P3189[HNOI2007] 海盗分宝参与者 3已保存回复 6
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @mhj9dclu
- 此快照首次捕获于
- 2025/11/03 22:51 4 个月前
- 此快照最后确认于
- 2025/11/03 22:51 4 个月前
CPP
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
// 读取输入参数
int l, w, m, n, h, a, d1, d2;
cin >> l >> w >> m >> n >> h >> a >> d1 >> d2;
// 读取输入矩阵(左上角为起点)
vector<vector<int>> input_matrix(l, vector<int>(w));
for (int i = 0; i < l; ++i) {
for (int j = 0; j < w; ++j) {
cin >> input_matrix[i][j];
}
}
// 转换为目标矩阵(左下角为(1,1))
vector<vector<int>> target_matrix(l + 1, vector<int>(w + 1, 0));
for (int i = 1; i <= l; ++i) {
// 垂直翻转输入矩阵
for (int j = 1; j <= w; ++j) {
target_matrix[i][j] = input_matrix[l - i][j - 1];
}
}
// 计算二维前缀和
vector<vector<int>> pre(l + 1, vector<int>(w + 1, 0));
for (int i = 1; i <= l; ++i) {
int row_sum = 0;
for (int j = 1; j <= w; ++j) {
row_sum += target_matrix[i][j];
pre[i][j] = pre[i - 1][j] + row_sum;
}
}
// 计算合法的列j
int max_j = a + (w - m + 1) / 2;
int max_possible_j = w - m + 1;
max_j = min(max_j, max_possible_j);
if (max_j < 1) {
cout << 0 << endl;
return 0;
}
vector<int> valid_j;
for (int j = 1; j <= max_j; ++j) {
valid_j.push_back(j);
}
// 计算每个(j, x)对应的矩形价值
int max_x = l - n + 1;
if (max_x < 1) {
cout << 0 << endl;
return 0;
}
vector<vector<int>> rect_value(valid_j.size(), vector<int>(max_x + 1, 0));
for (int idx = 0; idx < valid_j.size(); ++idx) {
int j = valid_j[idx];
int y2 = j + m - 1;
if (y2 > w) continue; // 确保不越界
for (int x = 1; x <= max_x; ++x) {
int x2 = x + n - 1;
if (x2 > l) continue; // 确保不越界
// 使用前缀和计算矩形价值
int sum_val = pre[x2][y2] - pre[x - 1][y2] - pre[x2][j - 1] + pre[x - 1][j - 1];
rect_value[idx][x] = sum_val;
}
}
// 动态规划初始化
vector<vector<int>> dp(h + 1, vector<int>(valid_j.size(), INT_MIN));
int mid_col = w / 2;
// 第一批(k=1)
for (int idx = 0; idx < valid_j.size(); ++idx) {
int j = valid_j[idx];
int max_val = 0;
// 从x=1开始寻找最大价值
for (int x = 1; x <= max_x; ++x) {
if (rect_value[idx][x] > max_val) {
max_val = rect_value[idx][x];
}
}
dp[1][idx] = max_val;
}
// 填充后续批次
for (int k = 2; k <= h; ++k) {
for (int curr_idx = 0; curr_idx < valid_j.size(); ++curr_idx) {
int curr_j = valid_j[curr_idx];
int best = 0;
for (int prev_idx = 0; prev_idx < valid_j.size(); ++prev_idx) {
if (dp[k-1][prev_idx] == INT_MIN) continue;
int prev_j = valid_j[prev_idx];
int required_d;
if (curr_j == prev_j) {
required_d = d1;
} else {
required_d = d2;
}
// 计算当前批次x的最小值
int min_x = -1;
for (int prev_x = 1; prev_x <= max_x; ++prev_x) {
if (rect_value[prev_idx][prev_x] == 0) continue;
int candidate = prev_x + required_d;
if (candidate > min_x) {
min_x = candidate;
}
}
if (min_x == -1 || min_x > max_x) continue;
// 寻找当前批次的最大价值
int curr_max = 0;
for (int x = min_x; x <= max_x; ++x) {
if (rect_value[curr_idx][x] > curr_max) {
curr_max = rect_value[curr_idx][x];
}
}
if (curr_max == 0) continue;
// 更新最佳值
if (dp[k-1][prev_idx] + curr_max > best) {
best = dp[k-1][prev_idx] + curr_max;
}
}
dp[k][curr_idx] = (best == 0) ? INT_MIN : best;
}
}
// 找到最大总价值
int result = 0;
for (int idx = 0; idx < valid_j.size(); ++idx) {
if (dp[h][idx] > result) {
result = dp[h][idx];
}
}
cout << result << endl;
return 0;
}
回复
共 6 条回复,欢迎继续交流。
正在加载回复...