• 优化 [Test, 动态规划]


    优化


    Descriptionmathcal{Description}

    给定长度为 NN 的序列 {ai}{a_i}, 从中选出 KK不相交区间, 从左到右记它们的和为 s1,s2...sns_1, s_2...s_n,
    请最大化下述合式
    i=1k1sisi+1sum_{i=1}^{k-1} s_i-s_{i+1}

    N<=3104, K<=min(N,200)N<=3*10^4, K <= min(N, 200)


    Solutionmathcal{Solution}

    F[i,j,k]设 F[i, j, k] 表示前 ii 个数, 组成 jj 个区间, (k=0,1,2,3)(k =0,1,2,3) 的最优值

    k=0k = 0 表示 选择ii 个数, Ai1>=Ai<=Ai+1A_{i-1} >= A_i <= A_i+1, 最优值,
    k=1k = 1 表示 选择或不选择ii 个数, Ai1>=Ai<=Ai+1A_{i-1} >= A_i<=A_i+1, 最优值,
    0,10, 1 表示当前数比两边都小时的情况, 只会对答案造成 负贡献.

    k=2k = 2 表示 选择ii 个数, Ai1<=Ai>=Ai+1A_{i-1} <= A_i >= A_{i+1}, 最优值,
    k=3k = 3 表示 选择或不选择ii 个数, Ai1<=Ai>=Ai+1A_{i-1} <= A_i >= A_{i+1} , 最优值.
    2,32, 3 表示当前数比两边都大时的情况, 只会对答案造成 正贡献.

    flag=2(j==1    j==K)flag =2 - (j==1 || j==K)
    F[i,j,0]=max(F[i1,j,0],F[i1,j1,3])flagAi F[i,j,1]=max(F[i,j,0],F[i1,j,1]) F[i,j,2]=max(F[i1,j,2],F[i1,j1,1])+flagAi F[i,j,3]=max(F[i,j,2],F[i1,j,3])  F[i, j, 0] = max(F[i-1,j,0], F[i-1, j-1,3]) - flag*A_i\ \ F[i,j,1] = max(F[i,j,0], F[i-1,j,1]) \ \ F[i,j,2] = max(F[i-1,j,2],F[i-1,j-1,1]) + flag*A_i\ \ F[i,j,3] = max(F[i,j,2], F[i-1,j,3]) \ \

    (flag>1)F[i,j,1]=max(F[i,j,1],F[i1,j1,1])F[i,j,3]=max(F[i,j,3],F[i1,j1,3]) F[i,j,1] = max(F[i,j,1],F[i-1,j-1,1]) \ ag{flag>1} F[i,j,3]=max(F[i,j,3], F[i-1,j-1,3])

    紫色部分为 状态的继承


    Codemathcal{Code}

    stdstd

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define reg register int 
    #define rep(i, a, b) for (reg i = a; i <= b; i++) 
    
    const int INF = 1e9, N = 30005, K = 205; 
    const double eps = 1e-6, phi = acos(-1.0); 
    ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;} 
    ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
    void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
    
    int f[N][K][4];
    int main() {
        freopen("optimization.in", "r", stdin);
        freopen("optimization.out", "w", stdout);
    	int n = read(), k = read();
    	rep(i, 1, k) rep(j, 0, 3) f[0][i][j] = -INF;
    	rep(i, 1, n) {   
    		int x = read();
    		rep(j, 1, k) {             
    			int flag = 2 - (j == 1 || j == k);
    			f[i][j][0] = max(f[i - 1][j][0], f[i - 1][j - 1][3]) - flag * x;//low 
    			f[i][j][1] = max(f[i - 1][j][1], f[i][j][0]);//
    
    			f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][1]) + flag * x;//high
    			f[i][j][3] = max(f[i - 1][j][3], f[i][j][2]);
    			if (flag - 1) {
    				f[i][j][1] = max(f[i][j][1], f[i - 1][j - 1][1]);
    				f[i][j][3] = max(f[i][j][3], f[i - 1][j - 1][3]);
    			}
    		}
    	}
    	printf("%d
    ", max(f[n][k][1], f[n][k][3]));
    }
    
    
  • 相关阅读:
    Qt开发经验小技巧226230
    Qt编写物联网管理平台37逻辑设计
    关于Qt数据库开发的一些冷知识
    Golang多线程垂直输出字符串
    Python合并两个有序数组
    Python找字符串中的最长回文子串
    qemu
    面试_链表类
    Sword nlohmann::json的使用
    聊聊 RPA 方向的规划:简单有价值的事情长期坚持做
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822599.html
Copyright © 2020-2023  润新知