​传送门aaaaaaaaaaa​

定义 f [ l ] [ r ] f[l][r] f[l][r]为区间 [ l , r ] [l,r] [l,r]最多消除几个数字

Ⅰ.首先可以分割为两个区间转移

f [ l ] [ r ] = f [ l ] [ k ] + f [ k + 1 ] [ r ] f[l][r]=f[l][k]+f[k+1][r] f[l][r]=f[l][k]+f[k+1][r]

Ⅱ.若 [ l + 1 , r − 1 ] [l+1,r-1] [l+1,r−1]消除干净了,且 a [ l ] a[l] a[l]和 a [ r ] a[r] a[r]等差

f [ l ] [ r ] = r − l + 1 f[l][r]=r-l+1 f[l][r]=r−l+1

Ⅲ.若存在一个 k k k,使得 [ i + 1 , k − 1 ] [i+1,k-1] [i+1,k−1]消除干净且 a [ i ] , a [ k ] a[i],a[k] a[i],a[k]等差

f [ l ] [ r ] = k − i + 1 + f [ k + 1 ] [ r ] f[l][r]=k-i+1+f[k+1][r] f[l][r]=k−i+1+f[k+1][r]

若存在一个 k k k,使得 [ k + 1 , j − 1 ] [k+1,j-1] [k+1,j−1]消除干净且 a [ k ] , a [ j ] a[k],a[j] a[k],a[j]等差

f [ l ] [ r ] = j − k + 1 + f [ i ] [ k − 1 ] f[l][r]=j-k+1+f[i][k-1] f[l][r]=j−k+1+f[i][k−1]

若存在一个 k k k,使得 [ i + 1 , k − 1 ] [i+1,k-1] [i+1,k−1]和 [ k + 1 , j − 1 ] [k+1,j-1] [k+1,j−1]消除干净,且 a [ i ] , a [ k ] , a [ j ] a[i],a[k],a[j] a[i],a[k],a[j]等差

f [ l ] [ r ] = r − l + 1 f[l][r]=r-l+1 f[l][r]=r−l+1

这样就转移完毕了

其实是比较套路的转移呢~被我切掉了hhhhh

#include <bits/stdc++.h>
using namespace std;
const int maxn = 309;
int t,a[maxn],d[maxn],f[maxn][maxn],n,m;
bool mp[maxn][maxn];
bool ok(int l,int r)
{
return f[l][r]==(r-l+1);
}
int main()
{
cin >> t;
while( t-- )
{
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=m;i++) cin >> d[i];

for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=1;k<=m;k++)
if( a[j]-a[i]==d[k] ) mp[i][j] = 1;

for(int l=2;l<=n;l++)
for(int i=1;i+l-1<=n;i++)
{
int j = i+l-1;
for(int k=i;k<j;k++)
{
f[i][j] = max( f[i][j],f[i][k]+f[k+1][j] );
int q = a[k]-a[i], w = a[j]-a[k];
if( q==w && mp[i][k] && ok(i+1,k-1) && ok(k+1,j-1) )
f[i][j] = l;//删除干净
if( q && mp[i][k] && ok(i+1,k-1) )
f[i][j] = max( f[i][j],k-i+1+f[k+1][j] );
if( w && mp[k][j] && ok(k+1,j-1) )
f[i][j] = max( f[i][j],j-k+1+f[i][k-1] );
}
if( f[i+1][j-1]==l-2&&mp[i][j] )//[i+1,j-1]被掏空
f[i][j] = l;
}

cout << f[1][n] << endl;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j] = mp[i][j] = 0;
}
}