[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);
}
}
浙公网安备 33010602011771号