B와 D : 우리 모두는, 곰의 정도는이 좋아하는 캐릭터를 아시다시피
D 게임 : 오늘, 그것은 게임을 발명했다.
영어 곰 정도는, 그래서 여기에없는 매우 훌륭 D, 더 깊은 의미하지만입니다 등차 수열의 대신 (산술 시퀀스 백과 사전) D.의 허용 오차
이 게임은 우선 설정된 공차 곰 {D}도를 갖고, 후 순차적으로 정렬 된 N 디지털 쓰기되도록한다. 규칙은 간단합니다 :
-
선택 X (X≥2) 현재의 연속 숫자 배열을 정렬 나머지;
-
X 1 체크 자릿수 연산 시퀀스를 구성 선택되고, 공차 d∈ {D};
-
두 충족하는 경우, 당신은 배열의 X 번호를 삭제할 수 있습니다;
-
당신이 더 많은 숫자를 삭제할 수 없습니다 때까지 1-3 단계를 반복합니다.
그 다음, 영리 충분한 경우 자리의 수 곰 최대의 정도가 삭제?
입력
첫번째 라인 정수 T (1≤T≤100) T.을 나타내는 데이터의 집합
두 정수 N에서 데이터의 각 세트는, M이 시작된다. 다음 라인은 N의 정수를 포함하고 순서화 된 어레이 아이 늘어서. 다음 라인 M은 정수이고, 디디 뮴 공차, 즉 주어진 세트 인
1≤N, M≤300
000≤Ai -1 000 000 000 000 000 Di≤1
출력
까지 삭제 디지털의 출력에 각 시험.
입력 샘플
. (3)
. (3) (1)
. (1) (2) (3)
. (1)
. (2) (3)
. (1) (2) 4
. 1 2
. 4 2
. 1. 3. 4. 3
. 1 2
샘플 출력
. 3
(2)
. (4)
아이디어 :
간격 DP
상태 F [I] [J]의 정의는 얼마나 많은 부분의 개수를 나타내는 경우는 전송 명확하지 않다, 제거 될 수있다.
J의 간격 내가 대신 프로그램, F [I] [J]의 가능성의 정의가 모두 삭제 할 수 있다면, 쉽게 처리 할 수있을 것이다.
하나의 명백한 결론은 다음과 같습니다 번호를 삭제하기 위해서는 삭제하고 세 가지를 삭제하는 두 가지로 분할 할 수 있습니다.
1의 간격 길이는 확실하게 삭제할 수 없습니다합니다. 도 2 및 3은 시간 간격의 길이는 별도 언급.
이어서 구간 [I, J]에서. 경우 토론의 두 가지 종류가 있습니다.
1.I j는 제거되었다 : 다음 F. 이때 [I] [J] F. = [I] [K] F.는 [. K + 1] [J]가로
본 : 2.I 및 j는 삭제되지 2 삭제로 나누었을 때 숫자 3과 번호를 삭제합니다. 두 개의 별도의 번호를 삭제하는 단계 [J]를 판정한다 - A [I ] 와 F [I + 1] [J - 1]. 삭제 수가 3 인 F [I + 1] [K - 1] F [K + 1] [J - 1] 토론이 [I]은 [K] 이 [J]
각 구간의 논의는 삭제하고 전면 F [i]는 i가 나타내는 참조의 최대 수를 정의 삭제 될 수있는 수는 될 수있다.
F는 [I]가 최대 = ([. 1 - I], F [J -. 1] + F를 I -. 1 + J)
N- 2 F 어레이로부터 계산 될 수있다.
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
map<int,int>mp;
int can[305][305];
int f[305],a[305];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
mp.clear();
memset(can,0,sizeof(can));memset(f,0,sizeof(f));
int n,m;scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
for(int i = 1,x;i <= m;i++)scanf("%d",&x),mp[x] = 1;
for(int len = 2;len <= n;len++)
{
for(int i = 1;i + len - 1 <= n;i++)
{
int j = i + len - 1;
if(len == 2)
{
if(mp[a[j] - a[i]])can[i][j] = 1;
continue;
}
else if(len == 3)
{
int k = j - 1;
if(a[j] - a[k] == a[k] - a[i] && mp[a[j] - a[k]])can[i][j] = 1;
continue;
}
for(int k = i + 1;k < j - 1;k++)
{
if(can[i][k] && can[k + 1][j])can[i][j] = 1;
}
if(can[i + 1][j - 1] && mp[a[j] - a[i]])can[i][j] = 1;
for(int k = i + 3;k < j - 2;k++)
{
if(can[i + 1][k - 1] && can[k + 1][j - 1])
{
if(a[j] - a[k] == a[k] - a[i] && mp[a[j] - a[k]])
{
can[i][j] = 1;
}
}
}
}
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j < i;j++)
{
f[i] = max(f[i],f[i - 1]);
if(can[j][i])f[i] = max(f[i],f[j - 1] + i - j + 1);
}
}
printf("%d\n",f[n]);
}
return 0;
}