AcWing 276. I-区域

题目链接

\(0\) 为单调伸长, \(1\) 为单调伸短。

\(f[i][j][l][r][x(0 / 1)][y (0 / 1)]\) 为第 \(i\) 行,已经选出\(j\)个格子,第\(i\)行选择了\([l, r]\) 区间的最大值。左右端点\(x, y\)分别为 单调伸长 / 单调伸短 的最大权值。

状态转移:

  1. \(x = 0, y = 0\),则 \(f[i][j][l][r][x][y] = max\{f[i - 1][j - (r - l + 1)][l'][r'][0][0]\} + cost(i, l, r)\) ,其中\(l <= l' <= r' <= r, j >= r - l + 1\)

  2. \(x = 0, y = 1\), 则 \(f[i][j][l][r][x][y] = max\{f[i - 1][j - (r - l + 1)][l'][r'][0][0 / 1]\} + cost(i, l, r)\),其中\(l <= l' <= r <= r', j >= r - l + 1\)

  3. \(x = 1, y = 0\), 则 \(f[i][j][l][r][x][y] = max\{f[i - 1][j - (r - l + 1)][l'][r'][0 / 1][0]\} + cost(i, l, r)\),其中\(l' <= l <= r' <= r, j >= r - l + 1\)
  4. \(x = 1, y = 1\), 则 \(f[i][j][l][r][x][y] = max\{f[i - 1][j - (r - l + 1)][l'][r'][0 / 1][0 / 1]\} + cost(i, l, r)\),其中\(l' <= l <= r <= r', j >= r - l + 1\)

初始状态: \(f[i][0][l][r][0][0] = 0 (0 <= i <= n, 1 <= l <= r <= m)\),其余为负无穷。

目标:\(max\{f[i][k][l][r][0 / 1][0 / 1]\} (1 <= i <= n)\)

输出方案只需通过状态转移延展即可。\(cost(i, l, r)\) 用前缀和计算​

时间复杂度\(O(n ^ 7)\)

C++ 代码

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 16;

struct S{
    int i, j, l, r, x, y;
}pre[N][N * N][N][N][2][2], t;

int n, m, k, a[N][N], f[N][N * N][N][N][2][2];
int ans = 0;

int inline cost(int i, int l, int r){
    return a[i][r] - a[i][l - 1];
}

void print(S x){
    if(x.j == 0) return;
    print(pre[x.i][x.j][x.l][x.r][x.x][x.y]);
    for(int i = x.l; i <= x.r; i++) 
        printf("%d %d\n", x.i, i);
}

int main(){
    memset(f, 0xcf, sizeof f);
    
    scanf("%d%d%d", &n, &m, &k);
    for(int r = 0; r <= n; r++) {
        for(int i = 1; i <= m; i++){
            for(int j = i; j <= m; j++)
                f[r][0][i][j][0][0] = 0;
        }
    }
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            scanf("%d", &a[i][j]), a[i][j] += a[i][j - 1];

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= k; j++){
            for(int l = 1; l <= m; l++){
                for(int r = l; r <= m; r++){
                    if(j < r - l + 1) continue;
                    
                    //x = 0, y = 0;
                    for(int l1 = l; l1 <= r; l1++){
                        for(int r1 = l1; r1 <= r; r1++){
                            int &v = f[i][j][l][r][0][0], val = f[i - 1][j - (r - l + 1)][l1][r1][0][0] + cost(i, l, r);
                            if(v < val) {
                                v = val, pre[i][j][l][r][0][0] = (S){i - 1, j - (r - l + 1), l1, r1, 0, 0};
                            }
                        }
                    }
                    //x = 0, y = 1;
                    for(int l1 = l; l1 <= r; l1++){
                        for(int r1 = r; r1 <= m; r1++){
                            for(int y1 = 0; y1 < 2; y1++) {
                                int &v = f[i][j][l][r][0][1], val = f[i - 1][j - (r - l + 1)][l1][r1][0][y1] + cost(i, l, r);
                                if(v < val) {
                                    v = val, pre[i][j][l][r][0][1] = (S){i - 1, j - (r - l + 1), l1, r1, 0, y1};
                                }
                            }
                        }
                    }

                    // x = 1, y = 0;
                    for(int l1 = 1; l1 <= l; l1++){
                        for(int r1 = l; r1 <= r; r1++){
                            for(int x1 = 0; x1 < 2; x1++) {
                                int &v = f[i][j][l][r][1][0], val = f[i - 1][j - (r - l + 1)][l1][r1][x1][0] + cost(i, l, r);
                                if(v < val) {
                                    v = val, pre[i][j][l][r][1][0] = (S){i - 1, j - (r - l + 1), l1, r1, x1, 0};
                                }   
                            }
                        }
                    }

                    // x = 1, y = 1;
                    for(int l1 = 1; l1 <= l; l1++){
                        for(int r1 = r; r1 <= m; r1++){
                            for(int x1 = 0; x1 < 2; x1++) {
                                for(int y1 = 0; y1 < 2; y1++) {
                                    int &v = f[i][j][l][r][1][1], val =  f[i - 1][j - (r - l + 1)][l1][r1][x1][y1] + cost(i, l, r);
                                    if(v < val) {
                                        v = val, pre[i][j][l][r][1][1] = (S){i - 1, j - (r - l + 1), l1, r1, x1, y1};
                                    }
                                }
                            }
                        }
                    }
                    if(j == k){
                        for(int x = 0; x < 2; x++) {
                            for(int y = 0; y < 2; y++) {
                                if(ans < f[i][j][l][r][x][y]) {
                                    ans = f[i][j][l][r][x][y], t = (S){i, j, l, r, x, y};
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    printf("Oil : %d\n", ans);
    print(t);
    return 0;   
}

转载于:https://www.cnblogs.com/dmoransky/p/11442169.html

### ACWing 785 快速排序 超时解决方案 当处理大规模数据集时,标准的快速排序实现可能会遇到性能瓶颈甚至超时。为了提高效率,可以考虑以下几种优化方法: #### 1. 随机化选取枢轴 通过随机选择枢轴来减少最坏情况的发生概率。这有助于平衡分区过程中的不均匀分布。 ```java import java.util.Random; public class QuickSort { private static final Random random = new Random(); public static void sort(int[] nums) { quicksort(nums, 0, nums.length - 1); } private static void quicksort(int[] a, int l, int r) { if (l >= r) return; // 使用随机索引作为枢纽元素 swap(a, l + random.nextInt(r - l + 1), r); int p = partition(a, l, r); quicksort(a, l, p - 1); quicksort(a, p + 1, r); } } ``` #### 2. 尾递归消除 采用迭代方式代替递归来降低栈空间消耗,并防止因过深调用而导致堆栈溢出错误。 ```java private static void quicksortIterative(int[] a, int lo, int hi) { Stack<Integer> stack = new Stack<>(); stack.push(lo); stack.push(hi); while (!stack.isEmpty()) { hi = stack.pop(); lo = stack.pop(); if (lo < hi) { int pi = partition(a, lo, hi); stack.push(lo); stack.push(pi - 1); stack.push(pi + 1); stack.push(hi); } } }[^1] ``` #### 3. 插入排序混合策略 对于较小规模子数组应用插入排序而非继续划分,因为后者在这种情况下反而更慢。 ```java if (hi <= lo + M) { Insertion.sort(aux, lo, hi); return; } // 对于小范围使用插入排序 ``` 其中 `M` 是一个经验值常量,默认设置为大约 10 左右即可获得良好效果。 这些改进措施能够显著提升快速排序算法的表现,在面对大数据输入时也能保持高效稳定的工作状态。值得注意的是,具体参数调整还需依据实际应用场景灵活决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值