算法设计与分析: 5-27 部落卫队问题

部落卫队问题是一个经典约束优化问题,目标是从居民中选择最多的人组成卫队,条件是任何两人间不能有仇敌关系。给定居民间的仇敌关系,通过回溯法可以找到最佳解决方案。数据输入包括居民数量和仇敌关系,Java实现是问题求解的一种方式。

5-27 部落卫队问题


问题描述

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

给定 byteland 部落中居民间的仇敌关系,编程计算组成部落卫队的最佳方案。

数据输入:
第 1 行有 2 个正整数 n 和 m,表示 byteland 部落中有 n个居民,居民间有 m 个仇敌关系。居民编号为 1,2,…,n。接下来的 m 行中,每行有 2 个正整数 u 和 v,表示居民 u 与居民 v 是仇敌。


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class BuLuoWeiDui {

    private static int n,m;
    private static boolean[][] enemy;
    private static int[] x,bestx;
    private static int cn,bestn;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            cn = 0;
            bestn = 0;

            n = input.nextInt();
            m = input.nextInt();

            enemy = new boolean[n+1][n+1];
            x = new int[n+1];
            bestx = new int[n+1];

            for(int i=1; i<=m; i++){
                int a = input.nextInt();
                int b = input.nextInt();
                enemy[a][b] = true;
                enemy[b][a] = true;
            }
            for(int i=0; i<=n; i++)
                x[i] = 0;

            backtrack(1);

            System.out.println(bestn);
            for(int i=1; i<=n; i++)
                System.out.print(bestx[i]+" ");
        }
    }

    private static void backtrack(int i){
        if(i > n){
            for(int j=1; j<=n; j++)
                bestx[j] = x[j];
            bestn = cn;
            return;
        }
        boolean ok = true;
        for(int j=1; j<i; j++)
            if(x[j]>0 && enemy[i][j]){
                ok = false;
                break;
            }
        if(ok){
            x[i]=1; cn++;
            backtrack(i+1);
            x[i]=0; cn--;
        }
        if(cn+n-i > bestn){
            x[i] = 0;
            backtrack(i+1);
        }
    }
}

Input & Output

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 


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

Reference

王晓东《计算机算法设计与分析》(第3版)P187

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值