20200310之种树 (动态规划 搜索)
题目描述
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
[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; }
- 点赞
- 收藏
- 分享
- 文章举报
- 20200312之第几天 (Excel)
- 20200314之新型导弹 (枚举 填空)
- 20200314之分苹果 (前缀和差分)
- 2019年第十届蓝桥杯(慢慢补)
- 算法设计与分析之 动态规划
- 开始记录
- C#接口笔记
- 20200313C#随手截图笔记
- Eplan截图笔记
- Driver files are not downloaded
- maven mybatis小结20200313
- jreble搜不到一直转圈或者提示商城没有的现象
- springboot2.2.6阿里镜像提示找不到
- 查看注解的作用
- 自己去阿里仓库找依赖遇到问题
- Youka:可创建任何YouTube视频的卡拉OK歌曲版本的免费网站
- 20200222 jzoj c组 生产武器(produce)
- 20200328 jzoj 羊羊整除(div)
- 20200307VJ总结
- 2019-01-03-Git相关操作