Interval dp upgrade review

Interval \ (dp \) to enhance the review

I have to say this wave problem is really simple. . .

Skills Summary:

1. Sometimes you can transfer and use of the backpack tired

2. If you encounter a similar section to add restrictions to limit the title can be directly thrown on the interval, considering a time \ ([l, r] \ ) is \ ([i, j] \ ) situation is completely contained

[BZOJ4897] [Thu Summer Camp2016] Transcript

A typical use of the backpack transfer, \ (DP [I] [J] \) represents this processed \ ([i, j] \ ) answers section

When the transition period intervals may be disposed of or directly from the first process has finished \ (dp [i] [j ] \) in take over, this can be maintained with a backpack

const int N=52,P=999983,INF=1e9;
 
int n,a,b,w[N];
int dp[N][N];
int tmp[N][N][N];
int id[N*N];
inline void cmin(int &a,int b){ ((a>b)&&(a=b)); }
inline void cmax(int &a,int b){ ((a<b)&&(a=b)); }
 
 
int main(){
    n=rd(),a=rd(),b=rd();
    w[0]=0,w[n+1]=1001;
    rep(i,1,n) w[i]=rd();
    rep(i,0,n+1) id[w[i]]=i;
    memset(dp,63,sizeof dp);
    rep(i,1,n) {
        int ma=0,mi=INF;
        rep(j,i,n) {
            ma=max(ma,w[j]),mi=min(mi,w[j]);
            dp[i][j]=(ma-mi)*(ma-mi)*b+a;
        }
    }
    drep(i,n,1) {
        memset(tmp,63,sizeof tmp);
        tmp[i-1][n+1][0]=0;
        rep(j,i,n) {
            drep(k,j,i) {
                rep(a,0,n+1) {
                    rep(b,0,n+1) {
                        cmin(tmp[j][a][b],tmp[k-1][a][b]+dp[k][j]);
                    }
                }
            }
            rep(a,0,n+1) {
                rep(b,0,n+1) if(tmp[j-1][a][b]<INF) {
                    cmin(tmp[j][id[min(w[a],w[j])]][id[max(w[b],w[j])]],tmp[j-1][a][b]);
                }
            }
            rep(a,1,n) {
                rep(b,1,n) if(tmp[j][a][b]<INF) {
                    cmin(dp[i][j],tmp[j][a][b]+(::a)+::b*(w[b]-w[a])*(w[b]-w[a]));
                }
            }
        }
    }
    printf("%d\n",dp[1][n]);
}
 
 

\[\ \]

\[ \ \]

[BZOJ4350] Pig Man brackets sequence battles

Consider limiting the time of the transfer \ (dp \)

First, this problem can be transformed into the problem out of the stack, the stack has a limit that is

\ (dp [i] [j ] \) , ie \ (I \) to \ (J \) number of points in this segment are popped program section

Then we move \ (dp [i] [j ] \) to enumerate the last out of the stack when \ (k \) , to check compliance with restrictions (just do not be too Cattleya number)

template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
 
 
 
 
const int N=310,P=998244353;
 
int n,m;
ll dp[N][N];
int s[N][N];
 
int main(){
    rep(kase,1,rd()){ 
        n=rd(),m=rd();
        int fl=1;
        memset(s,0,sizeof s);
        rep(i,1,m) {
            int a=rd(),b=rd();
            if(a==b) fl=0;
            else s[b][a]++;
        }
        rep(i,1,n) rep(j,1,n) s[i][j]+=s[i][j-1];
        rep(i,1,n) rep(j,1,n) s[i][j]+=s[i-1][j];
        if(!fl) {
            puts("0");
            continue;
        }
        memset(dp,0,sizeof dp);
        rep(i,1,n+1) dp[i][i-1]=1;
        drep(i,n,1) {
            rep(j,i,n) {
                rep(k,i,j) {
                    int t=s[k-1][j]-s[i-1][j]-s[k-1][k-1]+s[i-1][k-1];
                    if(t) continue;
                    t=s[j][k]-s[k][k]-s[j][k-1]+s[k][k-1];
                    if(t) continue;
                    dp[i][j]=(dp[i][j]+dp[i][k-1]*dp[k+1][j])%P;
                }
            }
        }
        printf("%lld\n",dp[1][n]);
    }
}

\[ \ \]

\[ \ \]

[BZOJ4758] [Usaco2017 Jan]Subsequence Reversal

\ (dp [i] [j ] [a] [b] \) represents \ ([i, j] \ ) of this section \ (LIS \) begin and end as \ (a, b \) answers

Then the \ (dp [i-1] [j], dp [i] [j + 1] \) transfer, both sides can consider reversing

const int N=52,P=998244353;
 
int n;
int a[N];
int dp[N][N][N][N];
 
 
 
int main(){
    rep(i,1,n=rd()) a[i]=rd();
    rep(i,1,n) dp[i][i][a[i]][a[i]]=1;
    rep(i,1,n-1) dp[i][i+1][min(a[i],a[i+1])][max(a[i],a[i+1])]=2;
    drep(i,n,1) {
        rep(j,i,n) {
            if(i>1) {
                rep(a,1,50) rep(b,a,50) {
                    cmax(dp[i-1][j][a][b],dp[i][j][a][b]);
                    if(::a[i-1]<=a) cmax(dp[i-1][j][::a[i-1]][b],dp[i][j][a][b]+1);
                }
            }
            if(j<n) {
                rep(a,1,50) rep(b,a,50) {
                    cmax(dp[i][j+1][a][b],dp[i][j][a][b]);
                    if(::a[j+1]>=b) cmax(dp[i][j+1][a][::a[j+1]],dp[i][j][a][b]+1);
                }
            }
            if(i>1 && j<n) {
                rep(a,1,50) rep(b,a,50) {
                    cmax(dp[i-1][j+1][a][b],dp[i][j][a][b]);
                    if(::a[j+1]<=a) cmax(dp[i-1][j+1][::a[j+1]][b],dp[i][j][a][b]+1);
                    if(::a[i-1]>=b) cmax(dp[i-1][j+1][a][::a[i-1]],dp[i][j][a][b]+1);
                    if(::a[j+1]<=a && ::a[i-1]>=b) cmax(dp[i-1][j+1][::a[j+1]][::a[i-1]],dp[i][j][a][b]+2);
                }
            }
        }
    }
    int ans=0;
    rep(i,1,50) rep(j,1,50) cmax(ans,dp[1][n][i][j]);
    printf("%d\n",ans);
}

\[ \ \]

\[ \ \]

[BZOJ3379] [Usaco2004 Open] Turning in Homework homework

It seems to be a more difficult problem

Observe, in fact, we can say that it must be on both sides of the room to go to, then go to the middle of the

Because if both sides of the room was not to finish, it will surely pass by the middle of the room to go after both sides of the room, then there is no need to go in the middle of

If this thought, it will simply

template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
 
const int N=1010,P=998244353;
 
int n,m;
typedef pair<int,int> Pii;
Pii a[N];
int dp[N][N][2];
 
int main(){
    n=rd(),rd(),m=rd();
    rep(i,1,n) a[i].first=rd(),a[i].second=rd();
    sort(a+1,a+n+1);
    memset(dp,10,sizeof dp);
    dp[1][n][0]=max(a[1].second,a[1].first),dp[1][n][1]=max(a[n].second,a[n].first);
    rep(i,1,n) {
        drep(j,n,i) {
            if(i>1) {
                cmin(dp[i][j][0],dp[i-1][j][0]+abs(a[i].first-a[i-1].first));
                cmin(dp[i][j][1],dp[i-1][j][0]+abs(a[j].first-a[i-1].first));
            }
            if(j<n) {
                cmin(dp[i][j][0],dp[i][j+1][1]+abs(a[i].first-a[j+1].first));
                cmin(dp[i][j][1],dp[i][j+1][1]+abs(a[j].first-a[j+1].first));
            }
            cmax(dp[i][j][0],a[i].second);
            cmax(dp[i][j][1],a[j].second);
        }
    }
    int ans=1e9;
    rep(i,1,n) cmin(ans,min(dp[i][i][1],dp[i][i][0])+abs(a[i].first-m));
    printf("%d\n",ans);
}
 

\[ \ \]

\[ \ \]

[BZOJ3928] [Cerc2014] Outer space invaders

Is the above-mentioned range limitation type

Each taking a section from one of the largest limit out to meet this limit, the limit is selected in a range in time shot

So all across this interval in this time point intervals will be destroyed

Do not cross this point in time directly plus

#include<cstdio> 
#include<cctype>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
 
 
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
 
char IO;
int rd(){
    int s=0,f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}
 
#define cmax(a,b) ((a<b)&&(a=b))
#define cmin(a,b) ((a>b)&&(a=b))

const int N=610;
 
int n;
int a[N],b[N],d[N];
int dp[N][N],ma[N][N];
int h[N],hc;
 
int main(){
    rep(kase,1,rd()) {
        hc=0;
        n=rd();
        rep(i,1,n) {
            a[i]=rd(),b[i]=rd(),d[i]=rd();
            h[++hc]=a[i];
            h[++hc]=b[i];
        }
        sort(h+1,h+hc+1),hc=unique(h+1,h+hc+1)-h-1;
        rep(i,1,hc) rep(j,i,hc) ma[i][j]=0,dp[i][j]=1e9;
        rep(i,1,n) {
            a[i]=lower_bound(h+1,h+hc+1,a[i])-h;
            b[i]=lower_bound(h+1,h+hc+1,b[i])-h;
            if(d[i]>d[ma[a[i]][b[i]]]) ma[a[i]][b[i]]=i;
        }
        rep(i,1,hc) rep(j,i+1,hc) {
            ((d[ma[i][j]]<d[ma[i][j-1]])&&(ma[i][j]=ma[i][j-1]));
            rep(k,i,j-1) ((d[ma[i][j]]<d[ma[k][j]])&&(ma[i][j]=ma[k][j]));
        }
        rep(i,1,hc) dp[i][i]=d[ma[i][i]];
        drep(i,hc,1) {
            rep(j,i,hc) {
                int id=::ma[i][j],ma=d[id];
                if(!id) dp[i][j]=0;
                else rep(k,a[id],b[id]) cmin(dp[i][j],dp[i][k-1]+dp[k+1][j]+ma);
            }
        }
        printf("%d\n",dp[1][hc]);
    }
}

\[ \ \]

\[ \ \]

POI2015 Washes

Subject description:

There are n car washes from left to right in a row, each store has a positive integer price \ (the p-[i] \) .

There \ (m \) personal consumption to come, the \ (i \) individuals will be passing the first \ (a [i] \) beginning up to the first \ (b [i] \) a car wash, and will choose the cheapest store once a consumer. But if the cheapest price is greater than \ (c [i] \) , then that person is not a car wash.

Please specify a price for each store, so that the sum of all of the money spent maximum.

Entry

The first line contains two positive integers \ (n-, m (. 1 <= n-<= 50, 1 <= m <= 4000) \) .

Subsequently m rows, each row comprising three positive integers \ (a [i], b [i], c [i] (1 <= a [i] <= b [i] <= n, 1 <= c [i] <= 500000) \ )

Export

The first line of output a positive integer that is the maximum value of the total consumption.

The second output line \ (n-\) positive integer, respectively for each car wash price \ (P [I] \) , requires \ (. 1 <= P [I] <= 500000 \) .

If a plurality of sets optimal solution, a group of any output.

Report problem-solving

Or an interval limits of the title, still define \ (dp [i] [j ] [k] \) represents consideration all \ ([l, r] \ ) is \ ([i, j] \ ) is completely contained and the interval within a minimum of \ (k \) answers

Enumeration value and the minimum value to appear, on both sides of the value of greater than or equal to a minimum value, and then considering all the cross sections of the answer to this location

#include<cstdio> 
#include<cctype>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<bitset>
using namespace std;
 
 
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
 
char IO;
int rd(){
    int s=0,f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}
 
 
const int N=52,M=4010;
 
int n,m;
vector <int> G[N][N];
int dp[N][N][M],f[N][N][M];
int h[M],hc;
int s[N][N][M],sum[N][N][M];
int to[N][N][M];
 
 
inline void chk(int &a,int b){ ((a<b)&&(a=b)); }
 
void Solve(int l,int r) {
    rep(i,l,r) {
        rep(j,1,hc) {
            int t=f[l][i-1][j]+f[i+1][r][j]+sum[l][r][j]-sum[l][i-1][j]-sum[i+1][r][j];
            if(t>dp[l][r][j]) dp[l][r][j]=t,to[l][r][j]=i;
        }
    }
    drep(j,hc,1) f[l][r][j]=max(dp[l][r][j],f[l][r][j+1]);
}
 
int res[N];
 
int dfs(int l,int r,int lim) {
    if(l>r) return 0;
    int ma=-1,id;
    rep(i,lim,hc) if(dp[l][r][i]>ma) ma=dp[l][r][i],id=i;
    res[to[l][r][id]]=id;
    dfs(l,to[l][r][id]-1,id);
    dfs(to[l][r][id]+1,r,id);
    return ma;
}
 
 
 
int main(){
    n=rd(),m=rd();
    rep(i,1,m) {
        int l=rd(),r=rd(),w=rd();
        h[++hc]=w;
        G[l][r].push_back(w);
    }
    sort(h+1,h+hc+1),hc=unique(h+1,h+hc+1)-h-1;
    rep(l,1,n) rep(r,l,n) rep(i,1,hc) rep(j,0,G[l][r].size()-1) s[l][r][i]+=((G[l][r][j]>=h[i])?h[i]:0);
    rep(k,1,hc) {
        rep(l,1,n) {
            rep(r,l,n) {
                sum[l][r][k]=sum[l][r-1][k];
                rep(i,l,r) sum[l][r][k]+=s[i][r][k];
            }
        }
    } // 预处理区间l,r内最小值为k的答案
    drep(i,n,1) {
        rep(j,i,n) {
            rep(k,1,hc) to[i][j][k]=i;
            Solve(i,j);
        }
    }
    printf("%d\n",dfs(1,n,1));
    rep(i,1,n) printf("%d ",h[res[i]]);
    puts("");
}
 

\[ \ \]

\[ \ \]

[BZOJ4856] [Jsoi2016] virus infection

I understand the meaning of the questions is: as long as the U-turn, it is necessary to save all finished to come back

Therefore, we consider the transfer of a section of the interval, the interval is resolved within each segment furthest point to come back to solve the nearest point

Each interval \ ([l, r] \ ) contributions are out directly be pretreated

Consider the interval \ ([l, r] \ ) for each point, or is first encountered on the rule in, or rule back then

Contributed two respectively \ (SUM [r] -sum [i] \) (due to multi-day stays), \ (3 * (RI) * A [i] + A [i] \) (so late Days)

(Probably such a meaning, emotional understanding of what, I may be wrong)

The recurrence can be

template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
 
const int N=3010;
 
int n;
ll a[N];
ll dp[N];
ll sum[N];
ll s[N][N];

int main(){
    n=rd();
    rep(i,1,n) a[i]=rd(),sum[i]=sum[i-1]+a[i];
    rep(i,1,n) {
        drep(j,i,1) {
            s[j][i]=s[j+1][i];
            s[j][i]+=sum[i]-sum[j];
            s[j][i]+=min(a[j]+(sum[i]-sum[j]),3*(i-j)*a[j]+a[j]);
        }
    }
    memset(dp,63,sizeof dp);
    ll ans=1e18;
    dp[0]=0;
    rep(i,1,n) {
        rep(j,1,i) {
            ll t=s[j][i]+(2*(i-j+1)+2*(i-j))*(sum[n]-sum[i]);
            cmin(dp[i],dp[j-1]+t);
            if(i==n) cmin(ans,dp[j-1]+s[j][i]+(2*(i-j+1)+(i-j))*(sum[n]-sum[i]));
        }
    }
    printf("%lld\n",ans-sum[n]);
}

\[ \ \]

\[ \ \]

[BZOJ3971] [WF2013] Matrjoşka

Understanding the problem is too painful

Probably means that each segment are consolidated into a few paragraphs \ ([1..x] \) consisting of

In fact, when combined contribution is minimum continuous period appear in \ ([i, k] \ ) or \ ([k + 1, j ] \) inside without opening, to be open to other contributions

template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
 
 
const int N=510;
 
const char *Im="Impossible";
 
int n;
int dp[N][N],ans[N];
int a[N],cnt[N][N],c[N];
int mi[N][N],mk[N][N];
 
 
 
int main(){
    rep(i,1,n=rd()) {
        a[i]=rd();
        cnt[i][a[i]]++;
        if(a[i]>n) return puts(Im),0;
    }
    rep(i,1,n) rep(j,1,n) cnt[i][j]+=cnt[i][j-1];
    rep(i,1,n) rep(j,1,n) cnt[i][j]+=cnt[i-1][j];
    rep(i,1,n){
        memset(c,0,sizeof c);
        mk[i][i-1]=1;
        mi[i][i-1]=1e9;
        rep(j,i,n) {
            mk[i][j]=mk[i][j-1];
            if(++c[a[j]]>=2) mk[i][j]=0;
            mi[i][j]=min(mi[i][j-1],a[j]);
        }
    }
    memset(dp,63,sizeof dp);
    rep(i,1,n) dp[i][i]=0;
    drep(i,n,1) rep(j,i,n) if(mk[i][j]) {
        rep(k,i,j-1) {
            if(mi[i][k]<mi[k+1][j]) cmin(dp[i][j],dp[i][k]+dp[k+1][j]+(j-i+1)-(cnt[k][mi[k+1][j]]-cnt[i-1][mi[k+1][j]]));
            else cmin(dp[i][j],dp[i][k]+dp[k+1][j]+(j-i+1)-(cnt[j][mi[i][k]]-cnt[k][mi[i][k]]));
        }
    }
    memset(ans,63,sizeof ans);
    ans[0]=0;
    rep(i,1,n) drep(j,i,1) {
        if(cnt[i][i-j+1]-cnt[j-1][i-j+1]==i-j+1) {
            cmin(ans[i],ans[j-1]+dp[j][i]);
        }
    }
    if(ans[n]<1e8) printf("%d\n",ans[n]);
    else puts(Im);
}

\[ \ \]

\[ \ \]

[BZOJ4426] [Nwerc2015] Better Productivity maximum productivity

The pile section is divided into \ (K \) groups, each to pay \ (> \ 0) , the maximum value of the total length of intersection

Here we should get rid of these intervals

First, an interval \ ([l, r] \ ) if we can contain other sections, then for its decision on only two cases

1. And he was an interval contained in a group, it does not affect the group's contribution

2. a person to open his own group

All other sections of the proposed contained, and the remaining sections are necessarily meet \ ([l, r] \ ) increments, this section we use \ (dp [i] [j ] \) before calculating \ (i \ ) intervals into \ (j \) answer group

Other sections, we are ignored, or select some of the largest single contribution to the self-contained group

Such transfer \ (dp \) is actually obvious \ (the n-^ 3 \) , but in fact can also be optimized to run \ (n \ leq 1000 \) data, leaving you gods you want it

template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
 
 
const int N=210;
 
int n,m,c;
int dp[N][N];
int len[N],lc;
struct Node{
    int l,r;
    bool operator < (const Node __) const {
        return r<__.r||(r==__.r&&l>__.l);
    }
}A[N];

int main(){
    n=rd(),m=rd();
    rep(i,1,n) A[i].l=rd(),A[i].r=rd()-1;
    sort(A+1,A+n+1);
    int ma=-1;
    rep(i,1,n) {
        if(ma<A[i].l) ma=A[i].l,A[++c]=A[i];
        else len[++lc]=A[i].r-A[i].l+1;
    }
    n=c;
    memset(dp,-63,sizeof dp);
    dp[0][0]=0;
    rep(i,1,n) {
        rep(j,1,i) {
            drep(k,i,1) {
                if(A[i].l<=A[k].r) cmax(dp[i][j],dp[k-1][j-1]+A[k].r-A[i].l+1);
                else break;
            }
        }
    }
    int ans=0;
    sort(len+1,len+lc+1,greater<int>());
    rep(i,1,lc) len[i]+=len[i-1];
    rep(i,max(1,m-lc),min(m,n)) cmax(ans,dp[n][i]+len[m-i]);
    printf("%d\n",ans);
}
 
 

Guess you like

Origin www.cnblogs.com/chasedeath/p/11787212.html