题目描述
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。
最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
数据规模和约定
对于全部数据,满足1< =m< =n< =30;
其中90%的数据满足m< =n< =20
-1000< =Ai< =1000
输入
输入的第一行包含两个正整数n、m。
第二行n个整数Ai。
输出
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
样例输入
7 3
1 2 3 4 5 6 7
样例输出
15
转自C语言网大佬题解的动态规划做法:
定义 dp[i][j]dp[i][j] 为 从位置 1 到位置 i 已经种了 j 棵树的情况下,美观度的最大值 (最优值), 索引从 1 开始。
动态转移方程:
dp[i][j] = max(dp[i-2][j-1] + beauty[i], dp[i-1][j])
分别对应位置 i 种树、不种树两种情况。
考虑到 N 个位置成环形,将问题的解分成两种情况以转变为非环形的子问题(从其他位置断开也可以)
1 号位置 种树
则 2、N 位置都不能种树, 问题转化为在 3 ~ N-1 这 N-2个位置上种 M-1棵树, 计算这个子问题时先不考虑1号位置的美观度,这个子问题的最优值为 dp[N-1][M-1] + beauty[1]
1 号位置 不种树
则问题为 在 2 ~ N 这 N-1 个位置上种 M 棵树,这个子问题的最优值为 dp[N][M], 仔细处理边界值
#include <bits/stdc++.h>
using namespace std;
const int minn=-1e9;
const int maxn=31;
int n,m; //n个位置 m棵树
int beauty[maxn];
int dp[maxn][maxn]; //第几个位置种了几棵树
int solve(){
for(int i=1;i<=m-1;i++)
//1种,则2、n都不种,转化为3~n-1种下m-1棵树
dp[1][i]=dp[2][i]=minn;
for(int i=3;i<n;i++)
for(int j=1;j<=m;j++)
dp[i][j]=max(dp[i-2][j-1]+beauty[i],dp[i-1][j]);
int ans1=dp[n-1][m-1]+beauty[1];
//1不种
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
dp[0][i]=dp[1][i]=minn;
for(int i=2;i<=n;i++)
for(int j=1;j<=m;j++)
dp[i][j]=max(dp[i-2][j-1]+beauty[i],dp[i-1][j]);
int ans2=dp[n][m];
return max(ans1,ans2);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&beauty[i]);
if(m>n/2){
printf("Error!");
return 0;
}
printf("%d",solve());
return 0;
}
大佬题解的搜索做法:
#include <bits/stdc++.h>
using namespace std;
const int maxn=31;
int n,m; //n个位置,m棵树
int beauty[maxn]; //美化值
bool isPlanted[maxn]; //是否种上了树
int ans=-1e9,temp=0; //最优值,临时值
bool check(int pos){ //是否可以种树
if(pos>n||isPlanted[pos]||isPlanted[(pos+1)%n]||isPlanted[(pos-1)%n])
return false;
return true;
}
void dfs(int pos,int cnt){ //位置,已经种了几棵树
if(cnt==m){
ans=max(ans,temp);
return ;
}
for(int i=pos;i<=n;i++){
if(check(i)){ //可种
temp+=beauty[i];
isPlanted[i]=true;
dfs(i,cnt+1);
isPlanted[i]=false;
temp-=beauty[i];
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&beauty[i]);
if(m>n/2){
printf("Error!");
return 0;
}
dfs(1,0);
printf("%d",ans);
return 0;
}