题目描述:
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门 得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤 肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。
最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
输入格式:
输入的第一行包含两个正整数n、m。
第二行n个整数Ai。
输出格式:
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
分析:
用递归来判断,每个位置有两种情况,放和不妨,考虑放的时候还要考虑它的前后(index+1)%n 和 (index-1+n)%n)这两个位置是否已经放了树了。最后在每种情况下选择最大值。
import java.util.Scanner;
public class Main {
static int n,m,ans,a[];
static boolean visited[];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
a = new int[n];//记录每个位置美观度
visited = new boolean[n];//记录每个位置是否被选择了
for (int i = 0; i < n; i++) {
a[i] = in.nextInt();
}
if(m>n/2){//不满足条件
System.out.println("Error!");
System.exit(0);
}
f(0,0,0);
System.out.println(ans);
}
/**
* @param x 已经选择了的美观度和
* @param cnt 选择的数量
* @param index 选择的位置
*/
private static void f(int x, int cnt, int index) {
if(cnt == m){
ans = Math.max(ans,x);//获取每次结果的最大值
return;
}
if(index >= n) return;
//如果index这个位置可以放
if(!visited[(index+1)%n] && !visited[(index-1+n)%n]){//判断前后是否已经被选择了
if(!visited[index]){
visited[index] = true;
f(x+a[index],cnt+1,index+1);
visited[index] = false;//回溯
}
}
//如果index这个位置不放
f(x,cnt,index+1);
}
}