C++笔试编程题5:种树

2019拼多多笔试编程题

种树


小多想在美化一下自己的庄园。他的庄园毗邻一条小河,他希望在河边种一排树,共 M 棵。小多采购了 N 个品种的树,每个品种的数量是 Ai (树的总数量恰好为 M)。但是他希望任意两棵相邻的树不是同一品种的。小多请你帮忙设计一种满足要求的种树方案。

  • 输入第一行包含一个正整数 N,表示树的品种数量。
    第二行包含 N 个正整数,第 i (1 <= i <= N) 个数表示第 i 个品种的树的数量。
    数据范围:1 <= N <= 1000 &&1 <= M <= 2000
  • 输出一行,包含 M 个正整数,分别表示第 i 棵树的品种编号 (品种编号从1到 N)。若存在多种可行方案,则输出字典序最小的方案。若不存在满足条件的方案,则输出"-"。

输入

3
4 2 1

输出

1 2 1 2 1 3 1

本题解法思路

  • 回溯法:剪枝进行深度优先进行遍历,遍历的过程记录和寻找最优解。
    剪枝条件: 当前剩余的位置数与数量最多的树关系 。a[i]>(t+1)/2

DFS+剪枝

#include 
using namespace std; 
bool DFS(vector<int> &a, vector<int> &res, int &t, int x){
    if(t==0) return true;
    for(int i=1;i<=a.size();i++){
        if(a[i]*2>t+1) return false;
        if(a[i]>0 && i!=x){
            a[i]--;
            t--;
            res.push_back(i);
            if(DFS(a, res, t, i)) return true;
            res.pop_back();
            t++;
            a[i]++;
        }
    }
    return false;
} 
int main(){
    int n, s=0;
    cin>>n;
    vector<int> a(n+1);
    vector<int> res;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s += a[i];
    }
    int t = s;
    if(DFS(a, res, t, 0)){
        for(int i=0;i<s;i++){
            if(i==s-1)
                cout<<res[i]<<endl;
            else
                cout<<res[i]<<" ";
        }
    }else{
        cout<<"-"<<endl;
    }
    return 0;
}

你可能感兴趣的:(笔试编程题)