社区讨论

问了一下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 条回复,欢迎继续交流。

正在加载回复...