部落卫队问题 (回溯)

原始部落byteland中的居民们为了争抢有限的资源,经常发生冲突。几乎每个居民都有它的仇敌。部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何两个人都不是仇敌。

输入格式:

第一行两个正整数n和m,表示byteland部落中有n个居民,居民间有m个仇敌关系, 0

输出格式:

输出部落卫队最佳组建方案中包含的居民人数。之后逐个输出卫队组成xi, 1<=i<=n, xi=0表示居民i不在卫队中,xi=1表示居民i在卫队中。

输入样例:

7 10
1 2
1 4
2 4
2 3
2 5
2 6
3 5
3 6
4 5
5 6

输出样例:

3
1 0 1 0 0 0 1 

代码实现:注意的点请看注解~

#include 
using namespace std;

int R[201][201] = {0}; //关系矩阵
int x[201] = {0}, cx[201] = {0}; //x[i]=1表示居民在卫队中,反之不在
int n, m; //n是人数,m是仇敌关系数量
int max_num = 0, cmax = 0; //卫队中居民人数

bool Bound(int t1) //约束函数:当前的居民在卫队中中是否有仇敌关系
{
    int j;
    for (j=1; jn)
    {
        if (max_num < cmax)
        {
            max_num = cmax;
            for (int i=1; i<=n; i++)
            {
                x[i] = cx[i];
            }
        }
        return;
    }
    //1
    if (Bound(t) == true) //当前居民在卫队中没有找到仇人
    {
        cx[t] = 1;
        cmax++;
        Back(t+1);
        cmax--;
        cx[t] = 0;
    }
    //0
    if (cmax+n-t >= max_num) //剪枝:再往下找,考虑理想情况,卫队居民人数也不可能比当前最大的多了
    {
        Back(t+1);
    }
}

int main()
{
    int u, v;
    cin >> n >> m;
    for (int i=1; i<=m; i++)
    {
        cin >> u >> v;
        R[u][v] = 1; R[v][u] = 1; //对称矩阵
    }
    Back(1);
    cout << max_num << endl;
    for (int i=1; i<=n; i++) //编号从1开始
    {
        cout << x[i] << " ";
    }
    return 0;
}

你可能感兴趣的:(算法,c++,算法)