HDU4283---You Are the One

Topic Description: Brief

Topic analysis:
Keyword: interval DP
It is easy to think of interval DP, but how to separate the two intervals, we need to find a standard to make the two end intervals independent without aftereffect.
As the diaosi continue to walk away, there is only one person left in the stack. Now consider the position of this person in the original queue, because it is the stack and it is the last one to leave. Then he must be everyone in front of him who left first, then this person went into the stack, and then all the others left behind, leaving him alone. This conclusion shows that we can definitely find a person, so that the left and right sides of the interval leave one after another, then enumerate the last person to leave.
F[i,j] denotes the minimum unhappiness for people between I and J.
The transfer equation is: F[i,j]=F[i,k-1]+F[k+1,j]+A[k]* (R-L)+(sum[R]-sum[k])*(k-L).

First is the realization of memory search:

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=105;

int T,INF,n;
int val[maxn],dp[maxn][maxn],sum[maxn];

int DFS(int L,int R){
    if(L>=R) return 0;
    if(dp[L][R]!=INF) return dp[L][R];

    int Res=INF;

    //To enumerate the last person to leave, the person behind must have left before him. 

    for(int k=L;k<=R;k++){
        int tmp=DFS(L,k-1)+DFS(k+1,R)+(sum[R]-sum[k])*(k-L)+val[k]*(R-L);
        if(Res>tmp) Res=tmp;
    }

    return dp[L][R]=Res;
}

int main(){
    scanf("%d",&T);
    for(int kase=1;kase<=T;kase++){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&val[i]),sum[i]=sum[i-1]+val[i];

        memset(dp,0x3f,sizeof(dp));
        INF=dp[0][0];

        printf("Case #%d: %d\n",kase,DFS(1,n));
    }

    return 0;
}

Convert to recursive form:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int M=105;

int Case;
int A[M],dp[M][M],Sum[M];
template<class T>inline void chkmin(T &a,T b){if(a>b || a==-1) a=b;}

template<class T>inline void Rd(T &res){
    char c;int f=1;res=0;
    while(c=getchar(),c<48)if(c=='-')f=-1;
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>47);res*=f;
}

//F[i,j]=F[i,k-1]+F[k+1,j]+A[k]*(R-L)+(sum[R]-sum[k])*(k-L)

int main(){
    Rd(Case);
    for(int cas=1;cas<=Case;cas++){
        memset(dp,0,sizeof(dp));

        int n;
        Rd(n);
        for(int i=1;i<=n;i++) scanf("%d",&A[i]),Sum[i]=Sum[i-1]+A[i];
        for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) dp[i][j]=INF;

        for(int i=n;i>=1;i--) for(int j=i+1;j<=n;j++)
            for(int k=i;k<=j;k++) chkmin(dp[i][j],dp[i][k-1]+dp[k+1][j]+A[k]*(j-i)+(Sum[j]-Sum[k])*(k-i));

        printf("Case #%d: %d\n",cas,dp[1][n]);
    }
    return 0;
}

Summary: When such a state is constantly changing and it is not good to divide the interval, the final state of event development can be considered to divide the event development, which is also one of the usual routines of interval DP.

Posted by Infinitive on Fri, 08 Feb 2019 07:33:17 -0800