D Game
众所周知,度度熊喜欢的字符只有两个:B 和D。
今天,它发明了一个游戏:D游戏。
度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
这个游戏是这样的,首先度度熊拥有一个公差集合$\{D\}$,然后它依次写下$N$个数字排成一行。游戏规则很简单:
1. 在当前剩下的有序数组中选择$X (X \geq 2)$ 个连续数字;
2. 检查$1$选择的$X$个数字是否构成等差数列,且公差 $d\in \{D\}$;
3. 如果$2$满足,可以在数组中删除这$X$个数字;
4. 重复 $1 - 3$ 步,直到无法删除更多数字。
度度熊最多能删掉多少个数字,如果它足够聪明的话?
今天,它发明了一个游戏:D游戏。
度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
这个游戏是这样的,首先度度熊拥有一个公差集合$\{D\}$,然后它依次写下$N$个数字排成一行。游戏规则很简单:
1. 在当前剩下的有序数组中选择$X (X \geq 2)$ 个连续数字;
2. 检查$1$选择的$X$个数字是否构成等差数列,且公差 $d\in \{D\}$;
3. 如果$2$满足,可以在数组中删除这$X$个数字;
4. 重复 $1 - 3$ 步,直到无法删除更多数字。
度度熊最多能删掉多少个数字,如果它足够聪明的话?
Input第一行一个整数$T$,表示$T(1 \leq T \leq 100)$ 组数据。
每组数据以两个整数 $N$,$M$ 开始 。接着的一行包括 $N$ 个整数,表示排成一行的有序数组 $A_{i}$。接下来的一行是 $M$ 个整数,即给定的公差集合 $D_{i}$。
$1 \leq N, M \leq 300$
$-1\ 000\ 000\ 000 \leq A_{i}, D_{i} \leq 1\ 000\ 000\ 000$
Output对于每组数据,输出最多能删掉的数字 。Sample Input
3 3 1 1 2 3 1 3 2 1 2 4 1 2 4 2 1 3 4 3 1 2
Sample Output
3 2 4
/* 每删除一段区间,假设区间长度为len,那么len一定能表示成2*i+3*j的形式,也就是每次可以只删除长度为2或3的长度即可 过程分两步: 1.先处理出f[i][j]=1/0,代表区间[i,j]能否全部删除,首先枚举一个中间点k,能由三种情况转移过来: ①如果[i,k]和[k+1,j]能被删除,那么[l,r]一定能被删除 ②如果[i+1,k]和[k+1,r-1]能被删除并且a[i]和a[j]能被删除,那么[l,r]一定能被删除 ③如果[i+1,k-1]和[k+1,r-1]能被删除并且a[i],a[k],a[j]能被删除,那么[l,r]一定能被删除 2.dp[i]表示到第i位最多能删除的数字个数,用f[][]转移即可 */ #include<iostream> #include<cstdio> #include<cstring> #include<map> #define maxn 310 using namespace std; int n,m,T,a[maxn],dp[maxn]; bool f[maxn][maxn]; map<int,int>mark; void work1(){ for(int i=2;i<=n;i++)if(mark[a[i]-a[i-1]])f[i-1][i]=1; for(int i=3;i<=n;i++)if(a[i-1]-a[i-2]==a[i]-a[i-1]&&mark[a[i]-a[i-1]])f[i-2][i]=1; for(int len=4;len<=n;len++) for(int i=1;i+len-1<=n;i++){ int j=i+len-1; for(int k=i+1;k<j;k++)f[i][j]|=(f[i][k]&f[k+1][j]); if(mark[a[j]-a[i]])f[i][j]|=f[i+1][j-1]; for(int k=i+1;k<j;k++) if(a[j]-a[k]==a[k]-a[i]&&mark[a[k]-a[i]]) f[i][j]|=f[i+1][k-1]&f[k+1][j-1]; } } void work2(){ for(int i=1;i<=n;i++){ dp[i]=dp[i-1]; for(int j=1;j<=i;j++){ if(!f[j][i])continue; dp[i]=max(dp[i],dp[j-1]+i-j+1); } } } int main(){ freopen("Cola.txt","r",stdin); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); mark.clear(); memset(f,0,sizeof(f)); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int x; for(int i=1;i<=m;i++){ scanf("%d",&x); mark[x]=1; } work1(); work2(); printf("%d\n",dp[n]); } }