HDOJ 1024 Max Sum Plus Plus
2017-05-24 19:40
239 查看
Max Sum Plus Plus
TimeLimit: 2000/1000 MS (Java/Others) Memory Limit:65536/32768 K (Java/Others)Total Submission(s): 28798 Accepted Submission(s): 10099
Problem Description
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be abrave ACMer, we always challenge ourselves to more difficult problems. Now youare faced with a more difficult problem.
Given a consecutive number sequence S1, S2,S3,
S4 ... Sx, ... Sn(1
≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define afunction sum(i, j) = Si
+ ... + Sj (1 ≤ i ≤j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and jwhich make sum(i1, j1)
+ sum(i2,j2) + sum(i3,
j3) + ... +sum(im, jm)
maximal (ix ≤iy ≤ jx
or ix ≤ jy≤ jx
is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't haveto output m pairs of i and j, just output the maximal summation of sum(ix,jx)(1
≤ x ≤ m) instead. ^_^
Input
Each test case will begin with two integers m and n, followed by n integers S1,S2,
S3 ... Sn.
Process to the end of file.
Output
Output the maximal summation described above in one line.
Sample Input
1 3 1 2 3
2 6 -1 4 -2 3 -23
Sample Output
6
8
Hint
Huge input, scanf and dynamic programming is recommended.
题意 :给出m和由n个整数(可正可负)组成的序列,要求在该序列中找出m个不相交的子序列(边界也不能重合),并使其最大。
思路:定义数组sum[],dp[][],ans[][],其中sum[i]表示序列中前i个数的和(前缀和),dp[i][j]表示序列中前j个数找出i个子序列的最大和,而ans[i][j]表示序列中前j个数找出i个子序列且第j个数必须取的最大和。那么分别写出dp,ans数组的状态转移方程。
对于ans数组,ans[i][j]=max(ans[i][j-1],dp[i-1][j-1])+sum[j]-sum[j-1],其中max函数中的第一个参数的对应的情况是此次加入的第j个数与前一个数连成一段,第二个参数的对应的情况是第j个数自己为一段。
对于dp数组,dp[i][j]=max(dp[i][j-1],ans[i][j]),分别对应于第j个数不加与加的情况。
状态转移方程构建完毕,但这样还不够,观察到题面的n很大,所以建立一个二维数组是不现实的,继续分析可得,每次更新值时,dp[i][j]最多只与它前一个状态dp[i-1][j]有关,故可以把第一维变成两种状态的更迭(0和1),而ans[i][j]状态转移时并没有用到第一维状态,故用一维数组实现即可,具体见代码。
#include <bits/stdc++.h>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define f(i,a,b) for(int i=(a);i<(b);++i)
typedef long long ll;
const int maxn= 1000005;
const int mod = 475;
const ll INF = 0x3f3f3f3f;
const double eps = 1e-6;
#define rush() int T;scanf("%d",&T);while(T--)
int dp[2][maxn];
int ans[maxn];
int sum[maxn];
int m,n;
int main()
{
int x;
while(~scanf("%d%d",&m,&n))
{
mst(dp,0);
sum[0]=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&x);
sum[i]=sum[i-1]+x;
}
int k=1;
for(int i=1; i<=m; i++)
{
for(int j=i; j<=n; j++)
{
if(i==j) //前j个数取j段,即所有数都取
dp[k][j]=ans[j]=sum[j]; //另外这个方程对ans数组起到了初始化的作用
else
{
ans[j]=max(dp[1-k][j-1],ans[j-1])+sum[j]-sum[j-1];
dp[k][j]=max(ans[j],dp[k][j-1]);
}
}
k=1-k; //dp数组第一维状态的更迭
}
printf("%d\n",dp[m%2]
);
}
return 0;
}
相关文章推荐
- HDOJ HDU 1024 Max Sum Plus Plus
- Hdoj 1024 Max Sum Plus Plus 【DP】
- hdoj Max Sum Plus Plus 1024 (DP) m个连续数组最大和
- HDOJ-1024 Max Sum Plus Plus (最大M子段和问题)
- HDOJ 1024 Max Sum Plus Plus -- 动态规划
- 暑期dp46道(18)--HDOJ 1024 Max Sum Plus Plus
- HDOJ-1024 Max Sum Plus Plus (最大M子段和问题)
- HDOJ 1024 Max Sum Plus Plus -- 动态规划
- HDOJ 1024 Max Sum Plus Plus
- HDOJ-1024 Max Sum Plus Plus (最大M子段和问题)
- hdoj 1024 Max Sum Plus Plus 【动态规划】
- hdoj 1024 Max Sum Plus Plus(最大m子段和)=-=
- HDU/HDOJ 1024 The Max Sum Plus Plus
- HDOJ 1024 Max Sum Plus Plus 最大M字段和
- HDOJ-1024 Max Sum Plus Plus
- hdoj 1024 Max Sum Plus Plus 【简单dp】
- hdoj 1024 Max Sum Plus Plus(m个子段最大和)
- hdoj1024 Max Sum Plus Plus(DP!DP!)
- HDOJ 题目1024 Max Sum Plus Plus(动态规划,不想交子段最大和)
- 每日三题-Day1-B(HDOJ 1024 Max Sum Plus Plus 最大m子段和)