AtCoder AGC035D Add and Remove (状压DP)

Topic Link

https://atcoder.jp/contests/agc035/tasks/agc035_d

answer

Want to hold out for two hours a-like pressure DP, how people find space only a dozen MB, turned violent on the line. . .
Consider that the original sequence of operations, we can build a map, a start there \ (n \) points no sides, a point every election about its unselected points plus two sides, the number of contribution is that it is a point the number of paths to the two left and right end points.
Then we can enumerate the election last point, the original sequence is split into two sections, the use of interval DP. The problem now is that we need to easily statistical contribution to the sum of a point. We observed that the \ ([l, r] \ ) this layer to \ ([1, n] \ ) bottom, or each expanded left (left end point \ (L \) is connected to a new \ (L '\) , \ (R & lt \) is connected to the \ (L' \) ), or to expand the right, so that a total process can be expressed as a length of not more than \ ((n-1) \ ) of the 01string, and from \ ( L \) or \ (R & lt \) reaches \ (1 \) or \ (n-\) of the program number obtained by the string (specifically, to maintain two variables \ (X = 1, Y = 1 \) , expanding the left when \ ((the X-, the y-) \ rightarrow (the y-the X-+, the y-) \) , the right time to expand \ ((x, y) \ rightarrow (x, x + y) \)). Each pre-processing 01coefficients corresponding string, can quickly calculate. The final DP state, \ (F [L] [R & lt] [K] [S] \) representing the interval \ ([L, R & lt] \) , 01run length \ (K \) , the string itself \ (S \) .
a total number of states is \ (\ sum ^ n_ {i = 1} 2 ^ i (n-i + 1) = O (2 ^ nn) \) , the transfer requires \ (O (n) \) of complexity (in fact, far less than), the total time complexity \ (O (2 ^ nn ^ 2) \) .
but if we set \ (f [l] [r ] [k] [S] \) memory of the words space complexity becomes \ (O (2 ^ nn ^ 3) \) , how do? Mental retardation after I put together a two-dimensional compression card with space constraints over ......
but the fact is repeated traversing a state of rare, no memory of not only before, but the speed is also twice as fast. (If not, then no pretreatment of the memory array, the \ (S \) string directly into the left and right end points are calculated several times on the line)
Found effect as follows:

(upper: lower no memory of: memoization)
Withered

Code

Memory of:

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
#define U ((1<<n)-1)
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 18;
const llong INF = 1e17;
llong f[N+1][N+1][(1<<N)+3];
llong val[(1<<N)+3];
llong a[N+3];
int n;

void updmin(llong &x,llong y) {x = min(x,y);}

llong dfs(int l,int r,int sta)
{
    if(f[l][r][sta]<INF) {return f[l][r][sta];}
    if(r-l<=1) return f[l][r][sta]=0ll;
    for(int i=l+1; i<r; i++)
    {
        updmin(f[l][r][sta],dfs(l,i,((sta<<1)|1)&U)+dfs(i,r,(sta<<1)&U)+a[i]*val[sta]);
    }
    return f[l][r][sta];
}

int main()
{
    scanf("%d",&n);
    for(int i=0; i<(1<<n)-1; i++)
    {
        int len = n; while(i&(1<<len-1)) {len--;} len--;
        llong x = 1ll,y = 1ll; for(int j=0; j<len; j++) i&(1<<j)?y+=x:x+=y; val[i] = x+y;
    }
    for(int i=0; i<n; i++) scanf("%lld",&a[i]);
    memset(f,10,sizeof(f));
    printf("%lld\n",dfs(0,n-1,(1<<n)-2)+a[0]+a[n-1]);
    return 0;
}

No memory of

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
#define U ((1<<n)-1)
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 18;
const llong INF = 1e17;
llong a[N+3];
int n;

void updmin(llong &x,llong y) {x = min(x,y);}

llong dfs(int l,int r,llong x,llong y)
{
    if(r-l<=1) return 0ll;
    llong ret = INF;
    for(int i=l+1; i<r; i++)
    {
        updmin(ret,dfs(l,i,x,x+y)+dfs(i,r,x+y,y)+a[i]*(x+y));
    }
    return ret;
}

int main()
{
    scanf("%d",&n);
    for(int i=0; i<n; i++) scanf("%lld",&a[i]);
    printf("%lld\n",dfs(0,n-1,1ll,1ll)+a[0]+a[n-1]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/12297613.html