ACM dynamic programming template (update ing...)

  • longest ascending subsequence problem
  • Multiple knapsack problem
  • Multiple Sections and Questions
  • division number problem
  • Multiset Combination Number Problem

1. The longest ascending subsequence problem

题目:There is a sequence a0,a1,...,an-1 of length n. Request the length of the longest ascending subsequence in this sequence. An ascending subsequence is a subsequence that satisfies ai<aj for any i<j.
思路:Define dp[i] as the minimum value of the last element in the ascending subsequence of length i+1 (INF if it does not exist)

//最长上升子序列问题
int dp[Max_n];

void solve(){
    memset(dp,0x3f,sizeof(dp));
    for(int i=0;i<n;i++)
        *lower_bound(dp,dp+n,a[i])=a[i];
    printf("%d\n",lower_bound(dp,dp+n,inf)-dp);
}

2. Multiple knapsack problem

题目:There are n kinds of items whose weight, value and quantity are wi, vi, and ci respectively. From these items, select items whose total weight does not exceed W, and find the maximum value of the sum of the selected items. (1≤n≤100, 1≤W≤50000)
思路:Binary-optimized multiple knapsacks.

//多重背包问题
int n,W;
int w[Max_n],v[Max_n],c[Max_n]; //重量、价值和数量
int dp[Max_W];

void ZeroOne_Pack(int w,int v){ 
    for(int i=W;i>=w;i--)
        dp[i]=max(dp[i],dp[i-w]+v);
}
void Complete_Pack(int w,int v){ 
    for(int i=w;i<=W;i++)
        dp[i]=max(dp[i],dp[i-w]+v);
}
int  Multi_Pack(){ 
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++){
        if(w[i]*c[i]>=W)Complete_Pack(w[i],v[i]);
        else {
            int k=1;
            while(k<c[i]){
                ZeroOne_Pack(w[i]*k,v[i]*k);
                c[i]-=k;
                k<<=1;
            }
            ZeroOne_Pack(w[i]*c[i],v[i]*c[i]);
        }
    }
    return dp[W];
}

3. Multiple Parts and Questions

题目:There are n numbers ai of different sizes, each of which is ci, and it is judged whether some of these numbers can be selected so that their sum is exactly k. (1 ≤n≤100, 1≤K≤100000)
思路:Define dp[i+1][j] as the maximum amount of the i-th number that can be left when the first i-numbers are added to get j (the case where i cannot be summed up is: -1)

//多重部分和问题
int n,k;
int a[Max_n],c[Max_n];
int dp[Max_k];

bool solve(){
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<n;i++){
        dp[0]=c[i];
        for(int j=1;j<=k;j++){ //递推关系
            if(dp[j]>=0)dp[j]=c[i];
            else if(j>=a[i]&&dp[j-a[i]]>0)dp[j]=dp[j-a[i]]-1;
            else dp[j]=-1;
        }
    }
    if(dp[k]>=0)return true;
    else return false;
}

4. The problem of division number

题目:There are n indistinguishable items, divide them into no more than m groups, and find the remainder of the division method number modulo M. (1 ≤m≤n≤1000)
思路:Consider the m division ai of n (i=1,2,3...), if for each ai>0, then {ai-1} corresponds to the m division of nm, and if There is ai=0, then it corresponds to the m-1 division of n. Define dp[i][j] as the total number of j divisions of i, then dp[i][j]=dp[i][j-1]+dp[ij][j].

//划分数问题
int n,m;
int dp[Max_n][Max_m];

void solve(){
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=0;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i>=j)dp[i][j]=(dp[i][j-1]+dp[i-j][j])%M;
            else dp[i][j]=dp[i][j-1];
        }
    }
    printf("%d\n",dp[n][m]);
}

5. Multiset Combination Number Problem

题目:There are n items, and the ith item has ai. Items of different kinds can be distinguished from each other but not of the same kind. How many ways are there to extract m items from these items? Find the remainder of the scheme number modulo M. (1≤n≤1000, 1≤m≤1000, 1≤ai≤1000, 2≤M≤10000)
思路:Define dp[i][j] as the total number of combinations taken out of j items in the previous i.
① When j≤a[i], dp[i][j]=dp[i-1][j]+dp[i-1][j] ② When j>s[i], dp[i][ j]=dp[i-1][j]+dp[i-1][j]-dp[i-1][j-1-a[i]].

//多重集组合数问题
int n,m;
int dp[2][Max_n];

void solve(){
    memset(dp,0,sizeof(dp));
    dp[0][0]=dp[1][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(j<=a[i])dp[i&1][j]=(dp[i&1][j-1]+dp[(i-1)&1][j])%mod;
            else dp[i&1][j]=(dp[i&1][j-1]+dp[(i-1)&1][j]-dp[(i-1)&1][j-1-a[i]]+mod)%mod;
            //在有取余的情况下,要避免减法运算的结果出现负数
        }
    }
    printf("%d\n",dp[n&1][m]);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324525621&siteId=291194637