关于连续子序列的题的总结:(dp)

本文深入讲解了三道经典的动态规划(DP)问题:hdu1003 MaxSum、hdu1231 最大连续子序列及hdu1024 MaxSumPlusPlus。通过分析状态转移方程,阐述了如何高效求解最大子序列和及其边界元素,提供了清晰的代码实现。

第一道题:hdu 1003 Max Sum

这到就是简单的dp题目:状态转移方程 dp[j] = max(dp[j-1] + a[j], a[j]);然后通过一个值来记录最值集合位置:

记录位置可以定义几个变量来记录:st, en, x,y;并且根据情况不断更新;

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const ll mod = 1e9 + 7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
int t;
int a[maxn];
int dp[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin >> t;
	int n;
	int kase = 0;
	int p = t;
	while(t--){
		cin >> n;
		kase ++;
		memset(dp,0,sizeof(dp));
		for(int i = 1; i <= n; i++)cin >> a[i];
		int end = 1, start = 1, x = 1, y  = 1;//对位置进行初始化
		int maxnn = -1001;
		for(int i = 1; i <= n; i++){
			if(dp[i-1]+a[i] < a[i]){
				x = i;
				y = i;//更新位置和最值;
				dp[i] = a[i];
			}else{
				dp[i] = dp[i-1] + a[i];
				y = i;	
			}
			if(maxnn < dp[i]){//记录最大值和开始和结束的位置,并且这是记录的最早到达最大值的位置;
				start = x;
				end = y;
				maxnn = dp[i];
			}
		}
		cout << "Case " << kase << ":" << endl;
 		cout << maxnn << " " << start << " " << end << endl;
		if(kase != p) cout << endl; 
	}
	return 0;
}

hdu 1231 最大连续子序列

这个就是和1003差不多知识他求的是最值的两边的值;

代码很相似:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
#define INF 0x3f3f3f3f
#define inf -2100000000
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 10000 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
int n;
int a[maxn];
int dp[maxn];
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n && n){
		for(int i = 1; i <= n; i++){
			cin >> a[i];
		}
		int st=1, en=1, x=1, y=1;
		memset(dp, 0, sizeof(dp));
		int cnt = inf;
		for(int i = 1; i <= n; i++){
			if(dp[i-1] + a[i] < a[i]){
				st = i;
				en = i;
				dp[i] = a[i];
			}else{
				en = i;
				dp[i] += dp[i-1] + a[i];
			}
			if(dp[i] > cnt){
				cnt = dp[i];
				x = st;
				y = en;
			}
		}
		if(cnt < 0){
			cout << 0 << " " << a[1] << " " << a[n] << endl;
		}else{
			cout << cnt << " " << a[x] << " " << a[y] << endl;
		}
	}
	return 0;
}

hdu 1024 Max Sum Plus Plus

这个题你上面两道都难,他的的状态转移方程不是很好写,有一个博客写的很好

https://www.cnblogs.com/kuangbin/archive/2011/08/04/2127085.html

代码入下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define INF  0x3f3f3f3f
#define inf -2100000000
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e6 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
int n, m;
int dp[maxn], f[maxn];
int a[maxn];
int main(){
	ios::sync_with_stdio(false);
	while(cin >> m >> n){
		for(int i = 1; i <= n; i++){
			cin >> a[i];
		}
		memset(f, 0, sizeof(f));
		memset(dp, 0, sizeof(dp));
		int maxnn;
		for(int i = 1; i <= m; i ++){
			maxnn = inf;
			for(int j = i; j <= n; j++){
				dp[j] = max(dp[j-1], f[j-1])+a[j];
				f[j-1] = maxnn;
				maxnn = max(maxnn, dp[j]);
			}
		} 
		cout << maxnn << endl;
	}
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值