P3146 [USACO16OPEN]248 G
f
[
i
]
[
j
]
f[i][j]
f[i][j]为完全合并
[
i
,
j
]
[i,j]
[i,j]获得的最大数,当
f
[
i
]
[
k
]
=
=
f
[
k
+
1
]
[
j
]
f[i][k]==f[k+1][j]
f[i][k]==f[k+1][j]时可以合并,
f
[
i
]
[
j
]
=
f
[
i
]
[
k
]
+
1
f[i][j]=f[i][k]+1
f[i][j]=f[i][k]+1。
#include<bits/stdc++.h>
using namespace std;
#define read(x) scanf("%d",&x)
#define maxn 250
int n;
int a[maxn+5];
int f[maxn+5][maxn+5];
int main() {
int ans=0;
read(n);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) f[i][i]=a[i],ans=max(ans,a[i]);
for(int j=1;j<=n;j++) {
for(int i=j-1;i>=1;i--) {
for(int k=i;k<j;k++) {
if(f[i][k]==f[k+1][j]&&f[i][k]!=0) f[i][j]=max(f[i][j],f[i][k]+1);
}
ans=max(ans,f[i][j]);
}
}
printf("%d",ans);
return 0;
}
[HNOI2010]合唱队
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]排出[i,j]队形,上一个入队的人的位置(0为队首,1为队尾)。
注意:
上一步方案数为0时不能转移。
第一个人和第二个人单独处理。
#include<bits/stdc++.h>
using namespace std;
#define read(x) scanf("%d",&x)
#define maxn 1000
#define maxm 2000
#define md 19650827
struct Pair{
int x,y;
Pair() {}
Pair(int _x,int _y) {
x=_x,y=_y;
}
bool operator < (const Pair e) const {
return x<e.x;
}
};
int n;
int a[maxn+5];
Pair b[maxn+5];
int f[maxn+5][maxn+5][2];
int main() {
read(n);
for(int i=1;i<=n;i++) read(a[i]),b[i]=Pair(a[i],i);
sort(b+1,b+1+n);
for(int i=1;i<=n;i++) a[b[i].y]=i;
for(int i=1;i<=n;i++) f[i][i][1]=f[i][i][0]=1;
for(int i=1;i<n;i++) {
if(a[i]<a[i+1]) f[i][i+1][0]=f[i][i+1][1]=1;
else f[i][i+1][0]=f[i][i+1][1]=0;
}
for(int j=1;j<=n;j++) {
for(int i=j-2;i>=1;i--) {
if(a[i]<a[i+1]&&f[i+1][j][0]) f[i][j][0]=(f[i][j][0]+f[i+1][j][0])%md;
if(a[i]<a[j]&&f[i+1][j][1]) f[i][j][0]=(f[i][j][0]+f[i+1][j][1])%md;
if(a[j]>a[i]&&f[i][j-1][0]) f[i][j][1]=(f[i][j][1]+f[i][j-1][0])%md;
if(a[j]>a[j-1]&&f[i][j-1][1]) f[i][j][1]=(f[i][j][1]+f[i][j-1][1])%md;
}
}
printf("%d",(f[1][n][0]+f[1][n][1])%md);
return 0;
}