回溯法(C++) 部落卫队问题

首先我们来看一下问题
先码在下面
在这里插入图片描述
我们知道回溯法一般生成子集树排列树,在这个问题中我们很容易得知我们要解决的问题是一个子集树,因为每个公民要么去要么不去,首先我们得找出可行解,当递归到了叶子节点的时候我们计算并更新最优值

#include <iostream>
#include <time.h>
using namespace std;
int maxc=0;//定义最优人数
int n;//居民人数
int m;//m对仇敌关系
int x[51][51]={0};//邻接矩阵
int rest=0;//剩余可选人数
int cur=0;//当前已选人数

int check(int t,int c[]){
for (int i = 1; i <t ; ++i)
{    //检查当前加进来的第t个村民是否和之前的居民存在仇敌关系
	if(c[i]){

		if(x[i][t]){
			return 0;
		          }
	         }
}
return 1;}

void traceback(int t,int c[]){

if (t>n)
{
	int temp=0;
	for (int i = 1; i < n+1; ++i)
	{
		temp+=c[i];
	}
	if (temp>maxc)
	{
		maxc=temp;
	}
	return ;
}
rest--;
if (check(t,c))//限制函数
{   cur++;//当前已选人数
	c[t]=1;//第t个居民被选择
	traceback(t+1,c);
	c[t]=0;
	cur--;
}

if ((rest+cur)>maxc)//限界函数
{
	traceback(t+1,c);
}
rest++;


}

int main()
{
	

cin>>n>>m;
rest=n;//最开始剩余价值是最多的 也就是所有居民都能选
int c[m+1]={0};//下标0做占位用 方便下标从1开始访问 赋值为0代表未选
for(int i=0;i<m;i++){

int a,b;

cin>>a>>b;
x[a][b]=1;
x[b][a]=1;
}

traceback(1,c);

cout<<maxc;

}

测试结果:
在这里插入图片描述

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值