题目大意:给定 种花
个花瓶,每种花插在花瓶上都有一个美观值 ,对于第
种花,满足第
种花插在的花瓶位置一定是在第
种花插在花瓶位置之前.每个花瓶只能插一种花。问将
朵花插入花瓶最大的美观值之和是多少.并且输出插入花瓶的位置方案。(如果有方案美观值相同,按字典序最小输出)
分析:动态规划.
表示第
种花插入第
个花瓶、前
种花插入前
个花瓶的最大美观值。
- 转移方程:
.
可以用前缀和维护。
- 最优解方案可以用
表示当前 前
种花插入前
个花瓶中可以获得最大的美观值,第
种花插入的花瓶位置。
因为是字典序最小所以转移时 就是最大美观值,获得方案,需要倒序遍历找到最优位置,然后倒置输出。
#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<<" ";
}
京公网安备 11010502036488号