华为非AI方向笔试真题 7月15号【手机多载波冲突选择】

手机多载波冲突选择(C++/Py/Java/Js/Go)题解

华为笔试真题 7月15号 非AI方向第二题 200分题型

题目内容

在手机通信中,为了提升网速,基站可以同时使用多个频段(称为载波聚合),每个频段提供一定的带宽,但存在以下限制:

  1. 每个频段最多选一个载波(不能同时选择同一频段的多个载波)。
  2. 冲突频段不能同时使用 (如 n1n1n1 和 n2n2n2 冲突,只能选其中一个)。
  3. 最多选择KKK个载波 (可以少于 KKK)。
    你的任务是:
  • 选择一组载波 ,使得 总带宽最大,同时满足上述约束。
  • 输出最大总带宽 ,并给出所选载波的 编号

输入描述

第一行 :NNN(载波总数,1≤N≤251 \le N \le 251≤N≤25)和 KKK(最多选 KKK 个载波,1≤K≤81 \le K \le 81≤K≤8,K≤NK \le NK≤N)。

第二行 :b1 b2 ... bNb1\ b2\ ...\ bNb1 b2 ... bN(每个载波的带宽,1≤bi≤10001 \le bi \le 10001≤bi≤1000)。

第三行 :f1 f2 ... fNf1\ f2\ ...\ fNf1 f2 ... fN(每个载波所属的频段,为 nnn 开头的字符串,如 n1n1n1、n2n2n2,不区分大小写,字符串长度不超过 101010)。

第四行 :CCC(冲突频段对数,0≤C≤250 \le C \le 250≤C≤25)。

接下来CCC行 :每行两个频段fa fbfa\ fbfa fb,表示 fafafa 和 fbfbfb 不能同时选(冲突关系不传递)。

输出描述

第一行 :最大总带宽。

第二行 :所选载波的 编号 (从 000 开始,按升序排列,数值序最小;组合有多种时,则输出数值序最小的一组)。

样例1

输入

复制代码
6 2
100 200 150 300 250 180
n78 n41 n78 n28 n41 n28
1
n28 n41

输出

复制代码
450
2 3

说明

选择带宽索引为 222 和 333 的两个带宽,即 150150150 和 300300300,总带宽为 450450450

样例2

输入

复制代码
3 2
10 10 10
n1 n2 n3
0

输出

复制代码
20
0 1

说明

最大带宽为 202020,因为每个频段带宽都相同,因此有 333 种组合:(0,1)(0,1)(0,1)、(0,2)(0,2)(0,2)、(1,2)(1,2)(1,2),输出排序后第一个组合 (0,1)(0,1)(0,1)

题解和思路

思路

实现思路:递归回溯

  1. 预处理根据分组内只能任选一以及分组冲突关系提取出每个节点冲突节点的二进制表现形式。
  2. 递归回溯 枚举所有方案,用位运算快速判断是否合法,并保留合法组合方案最大带宽、最小字典序结果。

C++

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int n, k;
vector<int> b;

// 最大带宽
int maxB = 0;
vector<int> res;

// 将字符串转换为小写
string toLowerCase(string text) {
    for (char &ch : text) {
        ch = static_cast<char>(
            tolower(static_cast<unsigned char>(ch))
        );
    }
    return text;
}

// 递归回溯
void dfs(int index, vector<int>& path, int selectedMask, int sum, int count, vector<int>& bandConflictMask) {
    if (index == n || count == k) {
        if (sum > maxB) {
            maxB = sum;
            res = path;
        }
        return;
    }
    
    for (int i = index; i < n; i++) {
        
        if ((selectedMask & bandConflictMask[i]) != 0) {
            continue;
        }
        sum += b[i];
        selectedMask |= (1 << i);
        path.push_back(i);
        dfs(i + 1, path, selectedMask, sum, count + 1, bandConflictMask);
        sum -= b[i];
        selectedMask -= (1 << i);
        path.pop_back();
    }
}



vector<int> getConflictMask(vector<string>& f,  vector<pair<string,string>>& conflict) {
    map<string, vector<int>> fPos;
    for (int i = 0; i < n; i++) {
        string lowF = toLowerCase(f[i]);
        fPos[lowF].push_back(i);
    }
    
    // 每个频段拥有频段的mask表示形式
    map<string, int> bandMask;
    vector<int> bandConflictMask(n , 0);
    for (auto[name, band] : fPos) {
        int mask = 0;
        for (int i = 0; i < band.size(); i++) {
            int pos = band[i];
            mask |= (1 << pos);
        }
        bandMask[name] = mask;
        
        // 处理每个频段
        for (int i = 0; i < band.size(); i++) {
            int pos = band[i];
            bandConflictMask[pos] = mask - (1 << pos);
        }        
    }
    
    // 处理冲突
    for (int i = 0; i < conflict.size(); i++) {
        string a = toLowerCase(conflict[i].first);
        string b = toLowerCase(conflict[i].second);
        if (bandMask.find(a) == bandMask.end() || bandMask.find(b) == bandMask.end()) {
            continue;
        }
        int aMask = bandMask[a];
        int bMask = bandMask[b];
        vector<int> apos = fPos[a];
        vector<int> bpos = fPos[b];
        for (int i = 0; i < apos.size(); i++) {
            bandConflictMask[apos[i]] |= bMask;
        }
        for (int i = 0; i < bpos.size(); i++) {
            bandConflictMask[bpos[i]] |= aMask;
        }     
    }    
    return bandConflictMask;
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    cin >> n >> k;
    b.reserve(n);
    for (int i = 0; i < n; i++) {
        cin >> b[i];
    }
    
    vector<string> f(n);
    for (int i = 0; i < n; i++) {
        cin >> f[i];
    }
    
    int c;
    cin >> c;
    vector<pair<string,string>> conflict;
    for (int i = 0; i < c; i++) {
        string a, b;
        cin >> a >> b;
        conflict.push_back({a, b});
    }
    
    vector<int> bandConflictMask = getConflictMask(f, conflict);
    vector<int> path;
    dfs(0, path, 0, 0, 0, bandConflictMask);
    cout << maxB << endl;
    for (int i = 0; i < res.size(); i++) {
        if (i > 0) {
            cout << " ";
        }
        cout << res[i];
    }
    return 0;
}

Java

java 复制代码
import java.util.*;

public class Main {
    static int n, k;
    static int[] b;

    // 最大带宽
    static int maxB = 0;
    static List<Integer> res = new ArrayList<>();

    // 将字符串转换为小写
    static String toLowerCase(String text) {
        return text.toLowerCase();
    }

    // 递归回溯
    static void dfs(int index, List<Integer> path, int selectedMask, int sum, int count, int[] bandConflictMask) {
        if (index == n || count == k) {
            if (sum > maxB) {
                maxB = sum;
                res = new ArrayList<>(path);
            }
            return;
        }

        for (int i = index; i < n; i++) {
            if ((selectedMask & bandConflictMask[i]) != 0) {
                continue;
            }

            sum += b[i];
            selectedMask |= (1 << i);
            path.add(i);

            dfs(i + 1, path, selectedMask, sum, count + 1, bandConflictMask);

            sum -= b[i];
            selectedMask ^= (1 << i);
            path.remove(path.size() - 1);
        }
    }

    static int[] getConflictMask(String[] f, List<String[]> conflict) {
        Map<String, List<Integer>> fPos = new HashMap<>();

        for (int i = 0; i < n; i++) {
            String lowF = toLowerCase(f[i]);
            fPos.computeIfAbsent(lowF, x -> new ArrayList<>()).add(i);
        }

        // 每个频段拥有频段的mask表示形式
        Map<String, Integer> bandMask = new HashMap<>();
        int[] bandConflictMask = new int[n];

        for (Map.Entry<String, List<Integer>> entry : fPos.entrySet()) {
            String name = entry.getKey();
            List<Integer> band = entry.getValue();

            int mask = 0;
            for (int pos : band) {
                mask |= (1 << pos);
            }

            bandMask.put(name, mask);

            // 处理每个频段
            for (int pos : band) {
                bandConflictMask[pos] = mask ^ (1 << pos);
            }
        }

        // 处理冲突
        for (String[] item : conflict) {
            String a = toLowerCase(item[0]);
            String bb = toLowerCase(item[1]);

            if (!bandMask.containsKey(a) || !bandMask.containsKey(bb)) {
                continue;
            }

            int aMask = bandMask.get(a);
            int bMask = bandMask.get(bb);

            for (int pos : fPos.get(a)) {
                bandConflictMask[pos] |= bMask;
            }

            for (int pos : fPos.get(bb)) {
                bandConflictMask[pos] |= aMask;
            }
        }

        return bandConflictMask;
    }

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

        n = sc.nextInt();
        k = sc.nextInt();

        b = new int[n];
        for (int i = 0; i < n; i++) {
            b[i] = sc.nextInt();
        }

        String[] f = new String[n];
        for (int i = 0; i < n; i++) {
            f[i] = sc.next();
        }

        int c = sc.nextInt();
        List<String[]> conflict = new ArrayList<>();

        for (int i = 0; i < c; i++) {
            String a = sc.next();
            String bb = sc.next();
            conflict.add(new String[]{a, bb});
        }

        int[] bandConflictMask = getConflictMask(f, conflict);

        dfs(0, new ArrayList<>(), 0, 0, 0, bandConflictMask);

        System.out.println(maxB);
        for (int i = 0; i < res.size(); i++) {
            if (i > 0) {
                System.out.print(" ");
            }
            System.out.print(res.get(i));
        }
    }
}

python

python 复制代码
n, k = map(int, input().split())
b = list(map(int, input().split()))

# 最大带宽
maxB = 0
res = []


# 将字符串转换为小写
def toLowerCase(text):
    return text.lower()


# 递归回溯
def dfs(index, path, selectedMask, total, count, bandConflictMask):
    global maxB, res

    if index == n or count == k:
        if total > maxB:
            maxB = total
            res = path[:]
        return

    for i in range(index, n):
        if (selectedMask & bandConflictMask[i]) != 0:
            continue

        path.append(i)
        dfs(i + 1, path, selectedMask | (1 << i), total + b[i], count + 1, bandConflictMask)
        path.pop()


def getConflictMask(f, conflict):
    fPos = {}

    for i in range(n):
        lowF = toLowerCase(f[i])
        fPos.setdefault(lowF, []).append(i)

    # 每个频段拥有频段的mask表示形式
    bandMask = {}
    bandConflictMask = [0] * n

    for name, band in fPos.items():
        mask = 0
        for pos in band:
            mask |= 1 << pos

        bandMask[name] = mask

        # 处理每个频段
        for pos in band:
            bandConflictMask[pos] = mask ^ (1 << pos)

    # 处理冲突
    for a, bb in conflict:
        a = toLowerCase(a)
        bb = toLowerCase(bb)

        if a not in bandMask or bb not in bandMask:
            continue

        aMask = bandMask[a]
        bMask = bandMask[bb]

        for pos in fPos[a]:
            bandConflictMask[pos] |= bMask

        for pos in fPos[bb]:
            bandConflictMask[pos] |= aMask

    return bandConflictMask


f = input().split()

c = int(input())
conflict = []
for _ in range(c):
    conflict.append(input().split())

bandConflictMask = getConflictMask(f, conflict)

dfs(0, [], 0, 0, 0, bandConflictMask)

print(maxB)
print(*res)

Javascript

js 复制代码
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const input = [];

rl.on("line", line => input.push(line));

rl.on("close", () => {
    let idx = 0;

    const [n, k] = input[idx++].split(" ").map(Number);
    const b = input[idx++].split(" ").map(Number);

    // 最大带宽
    let maxB = 0;
    let res = [];

    // 将字符串转换为小写
    function toLowerCase(text) {
        return text.toLowerCase();
    }

    function getConflictMask(f, conflict) {
        const fPos = new Map();

        for (let i = 0; i < n; i++) {
            const low = toLowerCase(f[i]);
            if (!fPos.has(low)) fPos.set(low, []);
            fPos.get(low).push(i);
        }

        // 每个频段拥有频段的mask表示形式
        const bandMask = new Map();
        const bandConflictMask = new Array(n).fill(0);

        for (const [name, band] of fPos.entries()) {
            let mask = 0;
            for (const pos of band) {
                mask |= (1 << pos);
            }

            bandMask.set(name, mask);

            // 处理每个频段
            for (const pos of band) {
                bandConflictMask[pos] = mask ^ (1 << pos);
            }
        }

        // 处理冲突
        for (const [aa, bb] of conflict) {
            const a = toLowerCase(aa);
            const bName = toLowerCase(bb);

            if (!bandMask.has(a) || !bandMask.has(bName)) continue;

            const aMask = bandMask.get(a);
            const bMask = bandMask.get(bName);

            for (const pos of fPos.get(a)) {
                bandConflictMask[pos] |= bMask;
            }

            for (const pos of fPos.get(bName)) {
                bandConflictMask[pos] |= aMask;
            }
        }

        return bandConflictMask;
    }

    // 递归回溯
    function dfs(index, path, selectedMask, sum, count, bandConflictMask) {
        if (index === n || count === k) {
            if (sum > maxB) {
                maxB = sum;
                res = [...path];
            }
            return;
        }

        for (let i = index; i < n; i++) {
            if ((selectedMask & bandConflictMask[i]) !== 0) {
                continue;
            }

            path.push(i);
            dfs(i + 1, path, selectedMask | (1 << i), sum + b[i], count + 1, bandConflictMask);
            path.pop();
        }
    }

    const f = input[idx++].split(" ");

    const c = Number(input[idx++]);
    const conflict = [];

    for (let i = 0; i < c; i++) {
        conflict.push(input[idx++].split(" "));
    }

    const bandConflictMask = getConflictMask(f, conflict);

    dfs(0, [], 0, 0, 0, bandConflictMask);

    console.log(maxB);
    console.log(res.join(" "));
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

var (
	n, k int
	b    []int

	// 最大带宽
	maxB int
	res  []int
)

// 将字符串转换为小写
func toLowerCase(text string) string {
	return strings.ToLower(text)
}

// 递归回溯
func dfs(index int, path []int, selectedMask int, sum int, count int, bandConflictMask []int) {
	if index == n || count == k {
		if sum > maxB {
			maxB = sum
			res = append([]int{}, path...)
		}
		return
	}

	for i := index; i < n; i++ {
		if (selectedMask & bandConflictMask[i]) != 0 {
			continue
		}

		path = append(path, i)
		dfs(i+1, path, selectedMask|(1<<i), sum+b[i], count+1, bandConflictMask)
		path = path[:len(path)-1]
	}
}

func getConflictMask(f []string, conflict [][2]string) []int {
	fPos := make(map[string][]int)

	for i := 0; i < n; i++ {
		low := toLowerCase(f[i])
		fPos[low] = append(fPos[low], i)
	}

	// 每个频段拥有频段的mask表示形式
	bandMask := make(map[string]int)
	bandConflictMask := make([]int, n)

	for name, band := range fPos {
		mask := 0
		for _, pos := range band {
			mask |= 1 << pos
		}

		bandMask[name] = mask

		// 处理每个频段
		for _, pos := range band {
			bandConflictMask[pos] = mask ^ (1 << pos)
		}
	}

	// 处理冲突
	for _, item := range conflict {
		a := toLowerCase(item[0])
		bb := toLowerCase(item[1])

		aMask, ok1 := bandMask[a]
		bMask, ok2 := bandMask[bb]

		if !ok1 || !ok2 {
			continue
		}

		for _, pos := range fPos[a] {
			bandConflictMask[pos] |= bMask
		}

		for _, pos := range fPos[bb] {
			bandConflictMask[pos] |= aMask
		}
	}

	return bandConflictMask
}

func main() {
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n, &k)

	b = make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &b[i])
	}

	f := make([]string, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &f[i])
	}

	var c int
	fmt.Fscan(in, &c)

	conflict := make([][2]string, c)
	for i := 0; i < c; i++ {
		fmt.Fscan(in, &conflict[i][0], &conflict[i][1])
	}

	bandConflictMask := getConflictMask(f, conflict)

	dfs(0, []int{}, 0, 0, 0, bandConflictMask)

	fmt.Println(maxB)
	for i, v := range res {
		if i > 0 {
			fmt.Print(" ")
		}
		fmt.Print(v)
	}
}
相关推荐
木木子221 小时前
# 待办清单应用 — HarmonyOS状态管理与列表渲染实战
华为·harmonyos
爱写代码的阿木2 小时前
基于鸿蒙OS开发附近社交游戏平台(五)-构建配置与签名部署
游戏·华为·harmonyos
爱写代码的阿森3 小时前
鸿蒙三方库 | harmony-utils之CharUtil字符类型判断详解
华为·harmonyos·鸿蒙·huawei
Alter12303 小时前
从堆算力到算存网协同,华为给出了Agent时代的新解法
人工智能·华为
木木子223 小时前
# 计数器应用 — 从零开始的HarmonyOS ArkUI开发实战
华为·harmonyos
爱写代码的森4 小时前
鸿蒙三方库 | harmony-utils之PasteboardUtil剪贴板数据读写详解
服务器·华为·harmonyos·鸿蒙·huawei
爱写代码的阿森5 小时前
鸿蒙三方库 | harmony-utils之StrUtil字符串空值判断详解
华为·harmonyos·鸿蒙·huawei
jin1233225 小时前
HarmonyOS ArkTS API 24实现声明式 UI 框架与 @Builder 组件复用模式构建三标签页智能账单应用
ui·华为·harmonyos
ov二号5 小时前
鸿蒙原生ArkTS布局方式之Image+renderMode图片渲染模式深度解析
华为·harmonyos