[atAGC050B]Three Coins

记$p_{i}$表示该位置是否有硬币

称使得$p_{i,i+1,i+2}$都变为1的操为对$i$的添加操作,使得$p_{i,i+1,i+2}$都变为0的操作为对$i$的删除操作

考虑一个简单的操作:若$p_{i}=1$,且$p_{i+1}=p_{i+2}=p_{i+3}=0$,可以通过执行对$i+1$的添加操作、对$i$的删除操作,使得$p_{i}$"移动"到$p_{i+3}$,我们将这个称之为对$i$的移动操作

接下来,我们证明一个$p_{i}$能通过添加和删除操作得到,当且仅当其能通过添加和移动操作得到:

由于移动操作是由添加和删除操作组合得到的,因此充分性满足

称$p_{i}=1$的来源为最后一次影响到$i$(由于最终$p_{i}=1$,必然是使其变为1)的操作位置,注意到对于来源相同的两个$p_{i}=p_{j}=1$,对其操作的时间也必然相同

考虑当执行对$i$删除操作时,对$p_{i},p_{i+1},p_{i+2}$的1的来源分类讨论,分为三种情况:

1.通过对$i$的添加操作得到,不妨将对$i$的删除操作提前到该次操作,显然无意义;

2.通过对$i-2$和$i+1$的添加操作,这也就是对$i$的移动操作;

3.通过对$i-1$和$i+2$的添加操作,这也就是对$i$和$i+1$的移动操作,等价于先对$i+1$、再对$i$的移动操作

由此,即证明删除操作都可以用添加和移动操作代替

接下来,考虑移动操作不会经过别的1,因此不会改变1的相对顺序,由此可以发现合法当且仅当:

选择第一次操作的3个1(模3不同余),将序列分为4部分(通过移动位置会发生改变),由于其他的1不会移动经过这3个1,要求每一个内部都是合法的

用$f_{i,j}$表示仅考虑区间$[i,j]$的最大值,若$i$或$j$中有一个未被选择,则$f_{i,j}=\max(f_{i+1,j},f_{i,j-1})$,否则分为两种情况:

1.左右端点是同一个,那么枚举中间的点转移即可(嵌套关系)

2.左右端点不是同一个,那么枚举两个的划分即可(并列关系)

时间复杂度为$o(n^{3})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 505
 4 int n,a[N],f[N][N];
 5 int main(){
 6     scanf("%d",&n);
 7     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
 8     for(int i=n;i;i--)
 9         for(int j=i+1;j<=n;j++){
10             f[i][j]=max(f[i+1][j],f[i][j-1]);
11             for(int k=i;k<j;k++)f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
12             for(int k=i+1;k<j;k+=3)
13                 if ((j-k)%3==1)f[i][j]=max(f[i][j],f[i+1][k-1]+f[k+1][j-1]+a[i]+a[j]+a[k]);
14         }
15     printf("%d",f[1][n]);
16 }
View Code

 

posted @ 2021-01-25 20:50  PYWBKTDA  阅读(219)  评论(2编辑  收藏  举报