这道题一开始被卡贪心思路然后发现大样例都过不了良心大样例
对于一个数列
2
4
2
3
4
3
2\ 4\ 2\ 3\ 4\ 3
2 4 2 3 4 3,贪心思路只取
4
4
4,但是显然取
2
3
2\ 3
2 3更优。
正解:区间
D
P
DP
DP,看到对于区间操作求最值,但又不是维护一些最大值最小值之类的区间性质的时候,就可以联想一下区间
D
P
DP
DP的方法。
具体做法:令
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示区间
i
∼
j
i\sim j
i∼j能取到的最大值,按区间长度从小到大转移。
f
[
i
]
[
j
]
=
m
a
x
k
(
f
[
i
]
[
k
]
+
f
[
k
+
1
]
[
j
]
)
f[i][j]=max_k(f[i][k]+f[k+1][j])
f[i][j]=maxk(f[i][k]+f[k+1][j])
如果有
a
[
i
]
=
=
a
[
j
]
a[i]==a[j]
a[i]==a[j],再判断此时要不要取这个数:
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
]
[
j
]
,
a
[
i
]
+
f
[
i
+
1
]
[
j
−
1
]
)
f[i][j]=max(f[i][j],a[i]+f[i+1][j-1])
f[i][j]=max(f[i][j],a[i]+f[i+1][j−1])
时间复杂度
O
(
n
3
)
O(n^3)
O(n3),但常数
1
6
\frac {1}{6}
61,可以通过此题。
D
P
y
y
d
s
!
DP\ yyds!
DP yyds!
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。-百度百科
然而这也是动态规划的本质,递推出所有可行解然后找到最优值,领略到这一点之后,一切
D
P
DP
DP都会变得了然起来。
不知道为什么总会有一些奇奇怪怪的话戳到我让我搞明白一些事情。
附上考场代码(还有我之前错误的贪心思路来着)
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
const int N=505;
int n,a[N],cnt=0;
int f[N][N];
int que[N];
int tot=0,tmp,tmp1,tmp2,maxx;
//inline void del(){
// tmp=tot;maxx=que[tmp];
// for(int i=tmp-1;i>=1;--i){
// if(que[i]>maxx) return;
// if(que[i]==maxx){
// cnt+=que[i];
// tot=i-1;
// return;
// }
// }
//}
inline int read(){
int cnt=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
return cnt*f;
}
signed main(){
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
n=read();
memset(f,0,sizeof(f));
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i){
tmp1=n-i;
for(int j=1;j<=tmp1;++j){
tmp2=j+i;
for(int k=j;k<=tmp2;++k){
f[j][tmp2]=max(f[j][tmp2],f[j][k]+f[k+1][tmp2]);
if(a[j]==a[tmp2]) f[j][tmp2]=max(f[j][tmp2],a[j]+f[j+1][tmp2-1]);
}
}
}
// for(int i=1;i<=n;++i){
// que[++tot]=a[i];
// del();
// }
printf("%d\n",f[1][n]);
// cerr<<(double)clock()<<endl;
return 0;
}