[DP]#hdu1003#hdu1087#hdu1159

hdu1003最大字段和

hdu1087 最长不降子序列(LIS)

hdu1159 最长公共子序列(LCS)

1003

1.全是负数的数据。(寻找最大和的时候,初始值要选择最小的int,而不是0,否则会有错误)

2.都满足条件的时候只输出第一种情况

#include<iostream>
#include<cstdio>
using namespace std;
const int maxnum=100000+1;
#define rep(i,n,m) for(int i=(n);i<=(m);++i)
#define re1(i,n) rep(i,1,n)
int a[maxnum];
int n;
int main(){
	int tcase,tnum=0;
	scanf("%d",&tcase);
	while(tcase--){
		scanf("%d",&n);
		re1(u,n){
			scanf("%d",&a[u]);
		}
		int sum=2147483647+1,from=1,to=0,j=1,b=-1;//最小的int(+1就溢出为最小int)
		rep(i,1,n){
			if(b<0){
				b=a[i];
				j=i;//j记录了每一段的开始节点。
			}else{
				b=b+a[i];
			}
			if(b>sum){
				sum=b;
				from=j;
				to=i;
			}
		}
		printf("Case %d:\n%d %d %d\n",++tnum,sum,from,to);
		if(tcase)
			printf("\n");

	}
}

1159

1.注意dp数组从1,1开始处理,退化情况就能统一处理,所以对应字符串用i-1,j-1

2.题目没有要求输出子序列,不过我写了一个递归函数。

3.这个是基本的题目,有空我再讲解吧。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,n,m) for(int i=(n);i<=(m);++i)
#define re1(i,n) rep(i,1,n)
#define re0(i,n) rep(i,0,n)
using namespace std;
const int maxnum=10000+1;
char a[maxnum],b[maxnum];
int dp[maxnum][maxnum];
int way[maxnum][maxnum];
template<class T>
void show(T a[][maxnum],int n,int m){
	re0(i,n){
		re0(j,m){
			cout<<a[i][j]<<' ';
		}
		cout<<endl;
	}
}
void makeSub(int i,int j){
	if(i==0 && j==0)
		return;
	if(way[i][j]==1){
		makeSub(i-1,j-1);
		cout<<b[j-1];
	}else if(way[i][j]==2){
		makeSub(i,j-1);
	}else
		makeSub(i-1,j);
}
int main(){
	while(~scanf("%s%s",a,b)){
		int la=strlen(a);
		int lb=strlen(b);
		re1(i,la)re1(j,lb){
			dp[i][j]=0;
			way[i][j]=0;
		}
		re1(i,la)re1(j,lb){
			if(a[i-1]==b[j-1]){
				dp[i][j]=dp[i-1][j-1]+1;
				way[i][j]=1;//<\
			//	cout<<a[i-1]<<' '<<b[i-1]<<endl;
			}
			else{
				if(dp[i][j-1]>=dp[i-1][j]){
					dp[i][j]=dp[i][j-1];
					way[i][j]=2;//<-
				}else{
					dp[i][j]=dp[i-1][j];
					way[i][j]=3;//<|
				}
			}
		}
		//show(dp,la,lb);
		printf("%d\n",dp[la][lb]);
//		makeSub(la,lb);
//		cout<<endl;
	}
}

  1087

1.动态规划的思想,dp[i]为A[i]为最后元素的最长上升子序列的长度,所以dp[i]=max(dp[j])+1,这里的j为小于(不等于)i大于等于1(从1开始),并且j为满足A[j]<A[i]的也就是说只有满足了A[i]比A[j]大,并且还要是之前最长的上升子序列,然后+1就是当前的i。能说的就这样了,这道题,本来dp应该存放长度,但是为了简单,我省去了长度,直接放和了。

#include<iostream>
#include<cstdio>
#define rep(i,n,m) for(int i=(n);i<=(m);++i)
#define re1(i,n) rep(i,1,n)
#define re0(i,n) rep(i,0,n)
const int maxnum=1000+1;
const int lowestint=-2147483647;
int a[maxnum],dp[maxnum];
using namespace std;
template<class T>
void show(T *a,int n,int m){
	rep(u,n,m){
		cout<<a[u]<<' ';
	}
	cout<<endl;
}
int main(){
	int n;
	while(scanf("%d",&n)){
		if(n==0)
			break;
		re1(u,n){
			scanf("%d",&a[u]);
			dp[u]=a[u];
		}
		dp[0]=0;
		re1(i,n){
			int bigcount=lowestint;
			int big=0;
			re1(j,i-1){
				if(a[j]<a[i]&&bigcount<dp[j]){
					bigcount=dp[j];
					big=j;
				}
			}
			dp[i]=dp[big]+a[i];
		}
		//show(dp,0,n);
		int big=0,bigcount=lowestint;
		re1(u,n)
			if(bigcount<dp[u]){
				big=u;
				bigcount=dp[u];
			}
		printf("%d\n",bigcount);
	}
}

  

  

posted @ 2012-12-11 19:04  GGGin  阅读(152)  评论(0编辑  收藏  举报