题目大意:给定图片说明 种花图片说明 个花瓶,每种花插在花瓶上都有一个美观值 ,对于第图片说明 种花,满足第图片说明 种花插在的花瓶位置一定是在第图片说明 种花插在花瓶位置之前.每个花瓶只能插一种花。问将图片说明 朵花插入花瓶最大的美观值之和是多少.并且输出插入花瓶的位置方案。(如果有方案美观值相同,按字典序最小输出)

分析:动态规划.

  • 图片说明 表示第图片说明 种花插入第图片说明 个花瓶、前图片说明 种花插入前图片说明 个花瓶的最大美观值。
  • 转移方程:图片说明 .
    图片说明 可以用前缀和维护。
  • 最优解方案可以用图片说明 表示当前 前图片说明 种花插入前图片说明 个花瓶中可以获得最大的美观值,第图片说明 种花插入的花瓶位置。
    因为是字典序最小所以转移时
    图片说明
  • 图片说明就是最大美观值,获得方案,需要倒序遍历找到最优位置,然后倒置输出。
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#define mk make_pair
#define pb push_back
using namespace std;

typedef long long ll;

int a[105][105];
ll dp[105][105];
int pos[105][105];

int main()
{
    int n,m;
    cin>>n>>m;
    for( int i=1;i<=n;i++ )
    {
        dp[i][i-1]=-1e10;
        for( int j=1;j<=m;j++ )    cin>>a[i][j];
        for( int j=i;j<=m;j++ )    dp[i][j]=dp[i-1][j-1]+a[i][j];
        for( int j=i;j<=m;j++ ) 
        {
            if( dp[i][j-1]>=dp[i][j] ) pos[i][j]=pos[i][j-1];
            else pos[i][j]=j;
            dp[i][j]=max(dp[i][j-1],dp[i][j]);
        }

    }
    int now=m;
    cout<<dp[n][m]<<endl;
    vector<int> ans;
    for( int i=n;i>=1;i-- )
    {
        ans.push_back(pos[i][now]);
        now=pos[i][now]-1;
    }
    reverse(ans.begin(),ans.end());
    for( auto v: ans )
     cout<<v<<" ";

}