Description

朵花, 个花瓶, 每朵花插在不同的花瓶都会产生不同的价值(正负数都有)。

你要按顺序依次将 朵花插入 个花瓶中,并保证第 朵花插入的位置 满足

  1. 求满足条件的插完 朵花的价值和的最大值。
  2. 打印价值和最大时从小到大插花的花瓶位置

Solution

对于问题一:

考虑将第 朵花插入第 位时代价和的最大值。记为

发现状态只跟 有关

但是这样暴力转移的复杂度高,需要优化。

不妨将 记为第 朵花插在前 个花瓶处代价的最大值。

此时的状态就只跟 相关联

所以我们就得到了状态转移方程

注意当 时我们要强制转移,因为此时第 朵花必须插在第 个花瓶处


对于问题二:

由于我们已经得到了第 朵花插在前 个花瓶时的最大值,我们就能够从后往前遍历寻找第一个 满足 的值, 就是插第 朵花的位置。如此反复即可。

code
#include <bits/stdc++.h>
#define ull unsigned long long int 
#define int long long int
#define endl '\n'
#define pb push_back
using namespace std;

const int N = 1E6 + 70,mod = 1e9 + 7;

inline int read(){
    char ch = getchar();
    int x =0,f =1;
    for(;!isdigit(ch);ch =  getchar())
        if(ch == '-') f = -1;
    for(; isdigit(ch);ch = getchar())
        x = (x << 1) + (x << 3) + ch - '0';
    return f * x;
}

int a[120][120];
int f[120][120];
/*
f[i][j] 前i朵花插在前j个瓶子中的最大美学值。
if(i == j)) f[i][j] = f[i - 1][j - 1] + a[i][j]; 必须插
*/

void dfs(int x,int y){
    if(x == 0) return ;
    while(f[x][y] == f[x][y - 1]) y --;
    dfs(x - 1,y - 1);
    cout << y << " ";
    
}

void slove(){
    int n  = read(),m = read();
    for(int i = 1;i <=n;i ++){
        for(int j = 1;j <= m;j ++){
            a[i][j] = read();
        }
    }

    for(int i = 1;i <= n;i ++){
        for(int j = i;j <= m;j ++){
            if(i == j){
                f[i][j] = f[i - 1][j - 1] + a[i][j];
                continue;
            }
            f[i][j] = max(f[i][ j - 1],f[i - 1][j - 1] + a[i][j]);
        }
    }
    cout << f[n][m] << endl;
    dfs(n,m);
}

signed main(){
    int T = 1;
    //T = read();
    while(T --){
        slove();
    }
    return 0;
}