传送门
题目描述起来有点麻烦,就不描述了.
关注题目给的特性,每朵花是按顺序插放的,这很符合dp中的阶段的特性.可以用dp[i][j]表示第i朵花插在第j个花瓶中的max.那转移方程就是:
dp[i][j] = max{dp[i-1][k],i-1<=k<=j-1}
这个方程因为j是固定的,内层还能够优化一下去掉一层循环,不过因为数据量比较小,直接暴力的做也可以.
输出方案可以用回溯的思想一个一个往上找(这也是dp问题找方案很常见的操作).
代码
#pragma GCC optimize(2)
#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e2+10;
inline void read(int &a){
int x = 0,f=1;char ch = getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){
x=x*10+ch-'0';ch=getchar();}
a = x*f;
}
int n,m,a[N][N],dp[N][N];
int main(){
cin >> n >> m;
fir(i,1,n) fir(j,1,m) cin >> a[i][j];
mem(dp,0x8f);
dp[0][0] = 0;
fir(i,1,n){
fir(j,1,min(m,m-(n-i))){
fir(k,i-1,j-1){
dp[i][j] = max(dp[i][j],dp[i-1][k]+a[i][j]);
}
}
}
int ans = INT_MIN;
fir(i,n,m) ans = max(ans,dp[n][i]);
cout << ans << endl;
int i = n;
vi vec;
while(i){
fir(j,1,m){
if(dp[i][j] == ans){
vec.pb(j);
ans -= a[i][j];
i--;
break;
}
}
}
reverse(ALL(vec));
for(auto x:vec) cout << x << " ";
return 0;
}
/*
dp[i][j] 第i个花放在第j个花瓶
*/