D Game HDU - 5693 (section DP)

As we all know, the degree of bears only two favorite characters: B and D.

Today, it invented a game: D game.

Bear degree of English is not very brilliant, so here is D, no profound meaning, but on behalf of that arithmetic progression (arithmetic sequence Encyclopedia) tolerance in D.

This game is such that, first of all have a degree of tolerance bears set {D}, and then it sequentially write the N digital aligned. The rules are simple:

  1. Select X (X≥2) consecutive numbers in the current remaining ordered array;

  2. X 1 is selected check digits constitute arithmetic sequence, and tolerance d∈ {D};

  3. If the two meet, you can delete the X numbers in the array;

  4. Repeat steps 1-3 until you can not delete more numbers.

Degree of bear up to the number of digits deleted if it is clever enough, then?
Input
first line an integer T, (1≤T≤100) set of data representing T.

Each set of data in two integers N, M starts. The next line contains N integers, an ordered array Ai lined. The next line M is an integer, i.e. a given set of tolerances Di.

1≤N,M≤300

000≤Ai 000 000 -1, 000 000 000 Di≤1
the Output
For each test, up to the output of the digital deleted.
The Input the Sample
. 3
. 3. 1
. 1 2. 3
. 1
. 3 2
. 1 2. 4
. 1 2
. 4 2
. 1. 3. 4. 3
. 1 2
the Sample the Output
. 3
2
. 4

Ideas:
the interval dp
If the definition of state F [i] [j] represents the number of how many sections can be removed, it is not obvious transferred.
But if the definition of the feasibility of the program, F [i] [j] on behalf of the interval i to j can delete all, it would be easier to handle.

One obvious conclusion is: to delete the number, it can be split into two to delete and delete three.

When the interval length of 1, certainly can not be deleted. 2 and 3, the length of the interval time separately discussed.
Then for the interval [i, j]. There are two kinds of case discussions.
1.i and j have been removed: then in this case F. [I] [j] = F. [I] [K] & F. [K +. 1] [j]
2.i and j are not deleted: This when divided into 2 delete delete the number 3 and number. Remove two separate numbers is determined a [j] - a [i ] and F [i + 1] [j - 1]. Remove the number 3 is F [i + 1] [k - 1] & F [k + 1] [j - 1], and discuss a [i] a [k] a [j]

A discussion of each interval can be deleted, and then define the maximum number of the front f [i] i represents the number is the number that can be deleted.
f [I] = max (f [I -. 1], f [J -. 1] + I -. 1 + J)
n- 2 can be calculated from f array.

#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;
}

Published 676 original articles · won praise 18 · views 30000 +

Guess you like

Origin blog.csdn.net/tomjobs/article/details/104213275
Recommended