HDU1024(dp)

it2023-08-30  67

题意描述

思路

使用 f [ i ] [ j ] f[i][j] f[i][j]来表示已经选择了 i i i段数,并且从前 j j j个数选择时的和的最大值。易得转移方程 f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i − 1 ] [ k ] ) + a [ j ] , i ≤ k ≤ j − 1 f[i][j]=max(f[i][j-1],f[i-1][k])+a[j] ,i≤k≤j-1 f[i][j]=max(f[i][j1],f[i1][k])+a[j]ikj1。转移方程的含义为以第 j j j个数为新的一组或将 a [ j ] a[j] a[j]分配到前一个组中。由于题目中的 n n n m m m太大,所以这样一定会超内存。观察发现, f [ i − 1 ] [ j − 1 ] f[i-1][j-1] f[i1][j1]可以使用 p r e [ j − 1 ] pre[j-1] pre[j1]来表示,并且状态方程也可以像背包问题一样优化掉一维,从而得到转移方程 f [ i ] = m a x ( f [ i − 1 ] , p r e [ i − 1 ] ) + a [ i ] f[i]=max(f[i-1],pre[i-1])+a[i] f[i]=max(f[i1],pre[i1])+a[i]

AC代码

#include<bits/stdc++.h> #define x first #define y second #define PB push_back #define mst(x,a) memset(x,a,sizeof(x)) #define all(a) begin(a),end(a) #define rep(x,l,u) for(ll x=l;x<u;x++) #define rrep(x,l,u) for(ll x=l;x>=u;x--) #define sz(x) x.size() #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef unsigned long long ull; typedef pair<int,int> PII; typedef pair<char,char> PCC; typedef long long ll; typedef pair<ll,ll> PLL; const int N=1e6+10; const int M=1e6+10; const int INF=0x3f3f3f3f; const int MOD=1e9+7; /* 独立思考 不要看测试样例 找性质 试着证明 写完后不盲目交 */ int a[N],f[N],pre[N]; void solve(){ int n,m; while(scanf("%d%d",&m,&n)!=EOF){ mst(f,0); mst(pre,0); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int res; for(int i=1;i<=m;i++){ res=-1e9; for(int j=i;j<=n;j++){ f[j]=max(f[j-1]+a[j],pre[j-1]+a[j]); pre[j-1]=res; res=max(res,f[j]); } } printf("%d\n",res); } } int main(){ //IOS; //freopen("test.txt", "r", stdin); //freopen("test.txt", "w", stdout); //int t;cin>>t; //while(t--) solve(); return 0; }
最新回复(0)