D Game

Problem Description
 
众所周知,度度熊喜欢的字符只有两个:B 和D。

今天,它发明了一个游戏:D游戏。

度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。

这个游戏是这样的,首先度度熊拥有一个公差集合{D},然后它依次写下N个数字排成一行。游戏规则很简单:

1. 在当前剩下的有序数组中选择X(X≥2) 个连续数字;

2. 检查1选择的X个数字是否构成等差数列,且公差 d∈{D};

3. 如果2满足,可以在数组中删除这X个数字;

4. 重复 1−3 步,直到无法删除更多数字。

度度熊最多能删掉多少个数字,如果它足够聪明的话?

 
Input
 
第一行一个整数T,表示T(1≤T≤100) 组数据。

每组数据以两个整数 N,M 开始 。接着的一行包括 N 个整数,表示排成一行的有序数组 Ai。接下来的一行是 M 个整数,即给定的公差集合 Di。

1≤N,M≤300

−1 000 000 000≤Ai,Di≤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
 

 题解:

  设定dp[1][n]位最后答案

  每次去删除2个或者3个连续,或不连续的数

  暴力区间dp

  我是用dfs写的比较好理解

  下面大牛给出的一组数组是题目数据没有给到的,刚好hack了我的daima

  下面已经更新,就是注意删除三个数的时候必须枚举

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include<map>
using namespace std;
const int N = , M = , mod = 1e9 + , inf = 0x3f3f3f3f;
typedef long long ll; int dp[N][N];
ll a[N],d;
map<ll,int > mp;
int dfs(int l,int r) {
if(dp[l][r]!=-) return dp[l][r];
int& ret = dp[l][r];
ret = ;
if(l>=r) return ret; if(l+==r) {
if(mp[a[r]-a[l]]) return (ret = );
else return (ret = );
} int tmp = ;
if(mp[a[r]-a[l]]) tmp+=;// cout<<a[r]-a[l]<<endl;
if(dfs(l+,r-)==((r-)-(l+)+)) ret = tmp+((r-)-(l+)+);
if(abs(a[r]-a[l])%==&&mp[(a[r]-a[l])/])
for(int i=l+;i<r;i++) {
tmp = ;
if(a[r]-a[i]==a[i]-a[l]&&mp[a[i]-a[l]]) {
tmp = ;
}
else continue;
if(tmp+dfs(l+,i-)+dfs(i+,r-)==r-l+) {
ret = r-l+;break;
}
} for(int i=l+;i<r;i++) {
ret = max(ret,dfs(l,i)+dfs(i+,r));
}
return ret;
}
int main() {
int T,m,n;
scanf("%d",&T);
while(T--) {
mp.clear();
memset(dp,-,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%I64d",&a[i]);
for(int i=;i<=m;i++) scanf("%I64d",&d),mp[d] = ;
printf("%d\n",dfs(,n));
}
return ;
} /*
1
7 2
1 5 8 101 59 62 201
100 3
*/
04-16 11:16