Description
种树
Input
输入描述:
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门 得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤 肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。
最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
输入样例:
7 3
1 2 3 4 5 6 7
Output
输出描述:
输入的第一行包含两个正整数n、m。
第二行n个整数Ai。
输出样例:
15
Sample Input 1
参考上文
Sample Output 1
参考上文
Hint
HINT:时间限制:1.0s 内存限制:256.0MB
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
Source
蓝桥杯练习系统 ID: 282 原题链接: http://lx.lanqiao.cn/problem.page?gpid=T282
坑点:没有给出具体的数据范围
思路:
将所有情况分成两种,一是一定包含第一个位置,二是不包含第一个位置
f[i][j] 表示的是从前1~i个位置中选出j个位置的最大值
初始化(非常重要):求最大值的初始化为负无穷,求最小值的初始化为正无穷,所以这里将所有不合法的状态初始化为负无穷
#include <iostream> #include <cstring> #include <algorithm> using namespace std ; const int N = 110,INF = 0x3f3f3f3f ; int f1[N][N],f2[N][N] ; int a[N] ; int n, m ; int main(){ cin >> n >> m ; for(int i=1;i<=n;i++){ cin >> a[i] ; } if(n<m*2 && m != 1 && n != 1){ cout << "Error!" << endl ; }else{ //分成两种情况,所有的方案中包含1和不包含1 for(int i=1;i<=m-1;i++){//f1[][]表示的是一定包含1 f1[0][i] = f1[1][i] = -INF ;//用负无穷表示不可到达,所以f[0][i]必不可达(i>=1),f1[1][i]必不可达(i>=2) } f1[1][1] = 0 ; for(int i=1;i<=n-1;i++){ for(int j=1;j<=m;j++){ if(i == 1){ f1[i][j] = max(f1[i][j],f1[i-1][j-1] + a[i]) ; }else{ f1[i][j] = max(f1[i-1][j],f1[i-2][j-1] + a[i]) ; } } } for(int i=1;i<=m;i++){ f2[0][i] = -INF ; f2[1][i] = -INF ;//第一个物品必不选 } for(int i=2;i<=n;i++){ for(int j=1;j<=m;j++){ f2[i][j] = max(f2[i-1][j],f2[i-2][j-1]+a[i]) ; } } cout << max(f2[n][m],f1[n-1][m]) << endl ; } return 0 ; }
...