成环间隔01背包

Posted morrowwind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了成环间隔01背包相关的知识,希望对你有一定的参考价值。

#include <bits/stdc++.h>
using namespace std;
//算法提高 种树
//这是01背包问题的变形
//环的处理方法 1.找到最小值的位置,预处理数组,比如 56 21 64 32 45 -> 21 64 32 45 56 21
//这样就相邻了而且21 21肯定不会同时选到
//2.还可以:第一个和最后一个只会选一个,
//那么就对 1...n-1 2...n进行处理,然后求最大值,注意要求两次dp,不是一次完成
int dp[101][101]={0},n,m,a[101][101]={0},v[101],v1[101];
int main()
{   
    int min=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        cin>>v1[i];
        if(v1[i]<v1[min]) min=i;
    }
    if(n/2<m) {cout<<"Error!
";return 0;}
    for(int i=min;i<=n;i++) v[i-min+1]=v1[i];
    for(int i=1;i<=min;i++) v[n-min+i+1]=v1[i];
    n++;
    dp[n][1]=v[n];
    a[n][1]=n;
    //这个是定义a的做法,a存放对应的dp数组的最左边位置的index
    // for(int i=n-1;i>=1;i--){
    //     for(int j=1;j<=m;j++){
    //         if(j>(n-i+1)/2) continue;
    //         if(dp[i+1][j]>dp[i][j]){
    //             dp[i][j]=dp[i+1][j];
    //             a[i][j]=a[i+1][j];
    //         }
    //         if(a[i+2][j-1]!=i+1){
    //             if(dp[i+2][j-1]+v[i]>dp[i][j]){
    //                 dp[i][j]=dp[i+2][j-1]+v[i];
    //                 a[i][j]=i;
    //             }
    //         } 
    //     }
    // }

    //也可以不定义a,因为dp[i+2][j-1]已经代表着不相邻了。
    for(int i=n-1;i>=1;i--){
        for(int j=1;j<=m;j++){
            if(j>(n-i+1)/2) continue;
            dp[i][j]=max(dp[i+1][j],dp[i+2][j-1]+v[i]);
        }
    }

    cout<<dp[1][m]<<endl;
    return 0;
}

 

以上是关于成环间隔01背包的主要内容,如果未能解决你的问题,请参考以下文章

机房测试7:gift (树形背包)

0-1背包问题的回溯法代码

「JSOI2019」神经网络(容斥+组合计数+背包dp)

动态规划_01背包_完全背包_多重背包_分组背包

01背包问题模板代码

代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些01背包问题,你该了解这些 滚动数组 416. 分割等和子集