题意:第2朵花放的花瓶编号要比第1朵花放的编号大。给出各花放各花瓶的价值,要价值和最大。
dp[i][j]表示第I朵花必须放在第j瓶中的前i朵花最大收益和。那么就等于dp[i-1][j]中的最大+当前花的价值。复杂度n^3。
看了别人的,还能用dp[i][j]表示第i朵花放第j瓶以内的最大收益和。那么,dp[i][j]要么不放第j瓶,就等于dp[i][j-1]要么放第j瓶,等于dp[i-1][j-1]中的最大+第i朵花放第j瓶价值。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <iomanip> #include <cstring> #include <map> #include <queue> #include <set> #include <cassert> using namespace std; const double EPS=1e-8; typedef long long lon; const lon SZ=120,INF=0x7FFFFFFF; lon arr[SZ][SZ],dp[SZ][SZ]; void work(lon n,lon m) { for(lon i=1;i<=m;++i)dp[1][i]=arr[1][i]; for(lon i=2;i<=n;++i) { for(lon j=1;j<=m;++j) { dp[i][j]=-INF; for(lon k=1;k<j;++k) { dp[i][j]=max(dp[i][j],dp[i-1][k]+arr[i][j]); } } } lon dst=*max_element(dp[n]+1,dp[n]+m+1); cout<<dst<<endl; vector<int> vct; for(int i=n;i>=1;--i) { for(int j=1;j<=m;++j) { if(dp[i][j]==dst) { vct.push_back(j); dst=dst-arr[i][j]; break; } } } for(int i=vct.size()-1;i>=0;--i) { if(i!=vct.size()-1)cout<<" "; cout<<vct[i]; }cout<<endl; } int main() { std::ios::sync_with_stdio(0); //freopen("d:\\1.txt","r",stdin); lon n,m; cin>>n>>m; for(lon i=1;i<=n;++i) { for(lon j=1;j<=m;++j)cin>>arr[i][j]; } work(n,m); return 0; }