1. 程式人生 > >關於連續子序列的題的總結:(dp)

關於連續子序列的題的總結:(dp)

第一道題: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;
}