hdu 1024和hdu 1244 两个最大和子序列 dp 优化

来源:互联网 发布:外贸通软件 编辑:程序博客网 时间:2024/05/22 06:17

hdu 1244

  题目链接

思路:

dp[i][j] 表示前i个数(包括第i个数)取了j段的最大和,则转移方程为 dp[i][j]=max(dp[i-1][j],dp[i-b[j]][j-1]+s[i]-s[i-b[j]])

#include<bits/stdc++.h>#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 100000007#define inf 0x3f3f3f3f#define exp 0.00000001#define  pii  pair<int, int>#define  mp   make_pair#define  pb   push_backusing namespace std;typedef long long ll;const int maxn=1e6+10;int gcd(int a,int b){return b==0?a:gcd(b,a%b);}int b[22],dp[1111][1111],n,m,s[1111];int main(){int w;while(~Ri(n)){if(n==0)break;Ri(m);s[0]=0;for(int i=1;i<=m;i++){Ri(b[i]);}for(int i=1;i<=n;i++){Ri(w);s[i]=s[i-1]+w;}CLR(dp,0);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){dp[i][j]=dp[i-1][j];if(i>=b[j])dp[i][j]=max(dp[i-1][j],dp[i-b[j]][j-1]+s[i]-s[i-b[j]]);}}Pi(dp[n][m]);}return 0;}

hdu 1024 

题意:

最大和子序列的加强版,但是n   1e6     m 范围没给出

dp[i][j]表示前i个数取j组的最大值(包括第i个数)

 转移方程: dp[i][j]=max(dp[i-1][j]+a[i],dp[k][j-1]+a[i]) j-1<=k<=i-1  (决策就是第i个数是独立成组还是和前一个数一起成组)

 因为我们这里的n和m都很大,显然这样是会爆的.

那么我们就来想想优化,我们由转移方程观察可以得出dp[i][j]的值,只与dp[i-1][j]和 dp[*][j-1]有关,那么我们可以开两个一维数组一个维护 dp的值 一个维护 前j-1到i-1取j-1组的最大值; 前i个数分成j-1组的最大值我们在计算过程中可以得到...然后维护一下即可

#include<iostream>#include<string.h>#include<algorithm>#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 100000007#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int maxn=1e6+10;int dp[maxn],pre[maxn];int a[maxn];int m,n; void solve(){CLR(dp,0);CLR(pre,0);int ma;for(int i=1;i<=m;i++){ma=-inf;for(int j=i;j<=n;j++){dp[j]=max(dp[j-1]+a[j],pre[j-1]+a[j]);pre[j-1]=ma;ma=max(ma,dp[j]);}}Pi(ma);}int main(){while(~scanf("%d %d",&m,&n)){for(int i=1;i<=n;i++)Ri(a[i]);solve();}return 0; }





1 0
原创粉丝点击