dp[i][j]=max(dp[i][j-1],dp[i-1][k])+a[j];
超时+空间
#include <iostream> #include <stdio.h> #include <string.h> #define MAX 100+5 #define INF -2100000000 using namespace std; int dp[MAX][MAX]; int main() { freopen("t.txt","r",stdin); int m,n,a[MAX]; while(scanf("%d%d",&m,&n)!=EOF) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); dp[i][i]=dp[i-1][i-1]+a[i]; } for(int i=1;i<=m;i++) { for(int j=i+1;j<=n;j++) { for(int k=i-1;k<j-1;k++) dp[i][j]=max(dp[i][j-1],dp[i-1][k])+a[j]; } } int res=INF; for(int i=m;i<=n;i++) { if(res<dp[m][i])res=dp[m][i]; } printf("%d\n",res); } return 0; }
改进一
去掉k层循环,将d[i-1][j-1]中保存前面的最大值,一直更新,
空间仍然太大
#include <stdio.h> #include <string.h> #define MAX 100+5 #define INF -2100000000 using namespace std; int dp[MAX][MAX]; int main() { freopen("t.txt","r",stdin); int m,n,a[MAX]; while(scanf("%d%d",&m,&n)!=EOF) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); dp[i][i]=dp[i-1][i-1]+a[i]; } for(int i=1;i<=m;i++) { dp[i-1][i]=INF; for(int j=i+1;j<=n;j++) { dp[i][j]=max(dp[i][j-1],dp[i-1][j-1])+a[j]; } } int res=INF; for(int i=m;i<=n;i++) { if(res<dp[m][i])res=dp[m][i]; } printf("%d\n",res); } return 0; }
改进二滚动数组
发现i只与i-1有关,将的dp[1][MAX]换成now[MAX],dp[0][MAX]换成pre[MAX]更好理解
dp[1][MAX]和dp[0][MAX]更适合另一种滚动方式
下次贴出来
#include <iostream> #include <stdio.h> #include <string.h> #define MAX 1000005 #define INF -2100000000 using namespace std; int dp[2][MAX],a[MAX]; int main() { //freopen("t.txt","r",stdin); int m,n; while(scanf("%d%d",&m,&n)!=EOF) { memset(dp,0,sizeof(dp)); //dp[0][0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=m;i++) { int j; int temp=INF; for( j=i;j<=n;j++) { dp[1][j]=max(dp[1][j-1],dp[0][j-1])+a[j]; dp[0][j-1]=temp;//0代表a[j]自成一段,故必须得至少隔开一个,所以用temp记录上次最大的与这次的a[j]隔开,例如j=3 temp=max(temp,dp[1][j]);//下次j=4时则dp[1][4]=max(dp[1][3],dp[0][3])+a[4];而dp[0][3]=temp即。。。 } } //int flag=m%2; int res=INF; for(int i=m;i<=n;i++) { if(res<dp[1][i])res=dp[1][i]; } printf("%d\n",res); } return 0; }