成环间隔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!\n";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; }