此题比较适合DP入门的人做一下。
最近刚学记忆化搜索,所以用记忆化搜索写了一个,dp[ i ]表示从第i个元素出发得到最大的上升子序列的和,状态转移方程dp[ i ]=max( d p [ i ] ,dp[ j ] ) + a[ i ](j>i&&a[i]<a[j])
代码如下:
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define eps 1e-9
#define N 1005
#define P system("pause")
using namespace std;
int n;
int a[N],dp[N],vis[N];
int dfs(int pos)
{
if(vis[pos]) return dp[pos];
vis[pos]=1;
for(int i=pos+1;i<n;i++)
{
if(a[pos]<a[i])
dp[pos]=max(dfs(i),dp[pos]);
}
dp[pos]+=a[pos];
return dp[pos];
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);cc
int i;
while(scanf("%d",&n)&&n)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
int maxx=0;
for(i=0;i<n;i++)
maxx=max(maxx,dfs(i));
printf("%d\n",maxx);
}
// P;
return 0;
}
下面是递推法计算状态转移方程的代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define eps 1e-9
#define N 1005
#define P system("pause")
using namespace std;
int n;
int a[N],dp[N];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);cc
int i,j;
while(scanf("%d",&n)&&n)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
int maxx=a[0];
dp[0]=a[0];
for(i=1;i<n;i++){
for(j=0;j<i;j++)
{
if(a[j]<a[i])
dp[i]=max(dp[i],dp[j]);
}
dp[i]+=a[i];
if(dp[i]>maxx) maxx=dp[i]; //dp[i]表示0到i(包括第i个元素)的最大上升子序列的和
}
printf("%d\n",maxx); //dp[]中的最大值就是最大上升子序列的和
}
// P;
return 0;
}