算法实验(四)——回溯/分支限界法

一、问题描述:

请你设计一个算法,找出一对互斥集合 A 和 B,使得 A和 B 包含的列的总数最大。

输入格式:

一个 1000 行 20 列的矩阵 matrix 作为测试用例,每行输入 20 列的元素,对矩阵找出满足题意的互斥集合。

输出格式:

输出两行,使得 A 的元素+B 的元素个数最大

第一行输出 A 集合中的所有元素(下标从 0 开始),以空格分开

第二行输出 B 集合中的所有元素,格式同上

如果,没有找到非空集合 A 和 B,则输出两行空行

二、代码实现:
 

#include<iostream>
using namespace std;

const int M = 25, N = 1010;
bool judge[M][M];					//记录两列是否矛盾
int a[N][M], choice[M];				//a数组记录输入
int sum[M];							//存储列的和
int ares = -1, bres = -1;			//存储A,B的最优选择
//asum,bsum是当前的A,B的元素和
//eps是列数差的绝对值,tc是当前最大列数和
int asum, bsum, eps = 100, tc;
//判断两列是否互斥
bool dispose(int x, int y)
{
    for (int i = 0; i < 1000; i++)
        if (a[i][x] + a[i][y] == 2)return false;
    return true;
}
//预处理judge[][]数组判断两列是否互斥
void init()
{
    for (int i = 0; i < 20; i++)
        for (int j = i + 1; j < 20; j++)
            if (dispose(i, j))judge[i][j] = judge[j][i] = true;
}
//得到choice[]数组
void get_choice()
{
    for (int i = 0; i < 20; i++)
    {
        int sum = 0;
        for (int j = 0; j < 20; j++)
            if (judge[i][j])sum += 1 << j;
        choice[i] = sum;
    }
}

//lowbit函数
int lowbit(int x)
{
    return x & (-x);
}
//返回二进制中1的个数
int get_one(int x)
{
    int res = 0;
    while (x)x -= lowbit(x), res++;
    return res;
}
//预处理所有列的和
void get_c()
{
    for (int i = 0; i < 20; i++)
    {
        int res = 0;
        for (int j = 0; j < 1000; j++)
            res += a[j][i];
        sum[i] = res;
    }
}

//得到数x二进制表示中所有列的和
int get_sum(int x)
{
    int k = 0, res = 0;
    while (x)
    {
        if (x & 1)res += sum[k];
        k++;
        x >>= 1;
    }
    return res;
}
//输出答案
void get_answer(int x)
{
    int k = 0, len = 20;
    while (len--)
    {
        if (x & 1)
            cout << k << " ";
        k++;
        x >>= 1;
    }
    cout << endl;
}
//同列数和列数差时比较排序次序
//返回true表示x应在y之后
bool compare(int x, int y)
{
    while (x && y)
    {
        if (lowbit(x) == lowbit(y))
        {
            x -= lowbit(x), y -= lowbit(y);
            continue;
        }
        else
        {
            if (lowbit(x) > lowbit(y))return true;
            return false;
        }
    }
    return false;
}
//更新函数
void update(int i, int j)
{
    ares = i, bres = j;
    tc = asum + bsum;
    eps = asum - bsum;
}

int main()
{
    for (int i = 0; i < 1000; i++)
        for (int j = 0; j < 20; j++)
            cin >> a[i][j];

    //预处理choice[]数组,judge[]数组,sum[]数组
    init(), get_choice(), get_c();
    //遍历A的所有选择
    for (int i = 1; i < 1 << 20; i++)
    {
        int temp = i, k = 0, j = -1;//j初始化-1是因为-1是111...111
        while (temp)
        {
            if (temp & 1)//如果这一位是1
                j = (j & choice[k]);//j和这一位的选择作&
            temp >>= 1;
            k++;
        }
        //得到i,j选择的列数
        asum = get_one(i), bsum = get_one(j);

        if (asum >= bsum && bsum)
        {
            if (asum + bsum > tc)//如果列数更大
                update(i, j);
            else if (asum + bsum == tc)//如果列数一样
            {
                //如果列数差的绝对值更小则更新
                if (asum - bsum < eps)
                    update(i, j);
                else if (asum - bsum == eps)//如果列数差相等
                {
                    if (compare(ares, i))
                        update(i, j);
                    else if(get_sum(ares) >= get_sum(bres) && get_sum(i) < get_sum(j))
                        update(i, j);
                }
            }
        }
    }

    if (~ares)//ares!=-1表示存在非空集合,~是取反,~(-1)=0
        get_answer(ares),get_answer(bres);

    else cout << endl << endl;
    return 0;
}

测试用例由于篇幅问题,请在资源中查找。输入用例和输出结果都有。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在Vue中,可以通过使用条件渲染和v-if指令来实现多个el-form-item的互斥。具体步骤如下: 1. 首先,在data中定义一个变量,用于表示当前选中的表单项的值,例如selectedItem。 2. 在el-form-item中添加v-if指令,根据selectedItem的值来判断是否显示该表单项。例如,如果要实现两个表单项的互斥,可以设置一个表单项的v-if为"selectedItem === 'item1'",另一个表单项的v-if为"selectedItem === 'item2'"。 3. 在el-form-item中添加相应的表单控件,例如el-input、el-select等。 4. 在需要触发互斥的事件(例如点击按钮或选择下拉框)中,通过修改selectedItem的值来切换显示的表单项。 下面是一个示例代码: ```html <template> <el-form> <el-form-item v-if="selectedItem === 'item1'"> <el-input v-model="inputValue1"></el-input> </el-form-item> <el-form-item v-if="selectedItem === 'item2'"> <el-select v-model="selectedValue2"> <el-option label="Option 1" value="option1"></el-option> <el-option label="Option 2" value="option2"></el-option> </el-select> </el-form-item> <el-button @click="toggleItem">Toggle Item</el-button> </el-form> </template> <script> export default { data() { return { selectedItem: 'item1', inputValue1: '', selectedValue2: '' }; }, methods: { toggleItem() { this.selectedItem = this.selectedItem === 'item1' ? 'item2' : 'item1'; } } }; </script> ``` 在上述示例中,根据selectedItem的值来切换显示的表单项。点击"Toggle Item"按钮时,会切换显示el-input和el-select两个表单项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏劫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值