#P1865. 2024.8.3-第二题-背包
-
1000ms
Tried: 190
Accepted: 42
Difficulty: 5
所属公司 :
米哈游
时间 :2024年8月3日
-
算法标签>DFS
2024.8.3-第二题-背包
题解
看似是背包,但考虑到 n 最大只有 15,DFS 枚举每个物品选或者不选即可
时间复杂度:O(215)
代码
c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Stock {
ll weight, value;
};
class StockSelector {
private:
int n, m, k;
vector<Stock> stocks;
vector<bitset<15>> mutexes;
ll maxValue = 0;
bool isCompatible(int stockIndex, const bitset<15>& selected) {
return (mutexes[stockIndex] & selected).none();
}
void dfs(int index, ll curValue, ll curWeight, bitset<15>& selected) {
if (index == n) {
maxValue = max(maxValue, curValue);
return;
}
dfs(index + 1, curValue, curWeight, selected);
if (isCompatible(index, selected) && curWeight + stocks[index].weight <= m) {
selected.set(index);
dfs(index + 1, curValue + stocks[index].value, curWeight + stocks[index].weight, selected);
selected.reset(index);
}
}
public:
void readInput() {
cin >> n >> m >> k;
stocks.resize(n);
mutexes.resize(n);
for (auto& [weight, value] : stocks) {
cin >> weight >> value;
}
for (int i = 0; i < k; ++i) {
int a, b;
cin >> a >> b;
--a; --b;
mutexes[a].set(b);
mutexes[b].set(a);
}
}
ll solve() {
bitset<15> selected;
dfs(0, 0, 0, selected);
return maxValue;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
StockSelector selector;
selector.readInput();
cout << selector.solve() << endl;
return 0;
}
java
import java.util.*;
public class Main {
static long res = 0;
static long rec = 0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
long m = in.nextLong();
int k = in.nextInt();
// 存储物品的体积和价值
long[][] wv = new long[n + 1][2];
for (int i = 1; i <= n; i++) {
wv[i][0] = in.nextLong(); // 体积
wv[i][1] = in.nextLong(); // 价值
}
// 处理互斥关系
Map<Integer, Set<Integer>> conflictMap = new HashMap<>();
for (int i = 1; i <= n; i++) {
conflictMap.put(i, new HashSet<>());
}
for (int i = 1; i <= k; i++) {
int a = in.nextInt(); // 互斥物品索引从0开始
int b = in.nextInt();
conflictMap.get(a).add(b);
conflictMap.get(b).add(a);
}
Set<Integer> ban = new HashSet<>();
Set<Integer> used = new HashSet<>();
dfs(1, n, m, 0, wv, conflictMap, ban, used);
// 输出结果
System.out.println(res);
}
public static void dfs (int index, int n, long m, long sumM, long[][] wv, Map<Integer, Set<Integer>> conflictMap, Set<Integer> ban, Set<Integer> used) {
res = Math.max(res, rec);
for (int i = index; i <= n; i++) {
if (used.contains(i) || ban.contains(i) || sumM + wv[i][0] > m) {
continue;
}
used.add(i);
ban.addAll(conflictMap.get(i));
sumM += wv[i][0];
rec += wv[i][1];
dfs(i + 1, n, m, sumM, wv, conflictMap, ban, used);
used.remove(i);
ban.removeAll(conflictMap.get(i));
sumM -= wv[i][0];
rec -= wv[i][1];
}
}
}
python
# n, m, k = list(map(int, input().split()))
# wList = []
# valList = []
# for _ in range(n):
# w, val = list(map(int, input().split()))
# wList.append(w)
# valList.append(val)
# def insertIntoMap(k, v, exclusions):
# if k in exclusions:
# exclusions[k].append(v)
# else:
# temp = []
# temp.append(v)
# exclusions[k] = temp
# exclusions = {}
# for _ in range(k):
# a, b = list(map(int, input().split()))
# insertIntoMap(a, b, exclusions)
# insertIntoMap(b, a, exclusions)
# def checkValid(contains, excluList):
# for contain in contains:
# if contain in excluList:
# return False
# return True
# maxVal = 0
# def dfs(contains, wtotal, valTotal, startIndex):
# global maxVal
# if wtotal > m:
# return
# elif valTotal > maxVal:
# maxVal = valTotal
# i = startIndex
# for i in range(startIndex, n+1):
# excluList = exclusions[i]
# if not checkValid(contains, excluList):
# continue
# contains.append(i)
# dfs(contains, wtotal + wList[i-1], valTotal + valList[i-1], i+1)
# contains.pop()
# dfs([], 0, 0, 1)
# print(maxVal)
from collections import defaultdict
n,m,k = map(int, input().split())
stocks = []
for _ in range(n):
a,b = map(int, input().split())
stocks.append((a,b))
mutexs = defaultdict(set)
for _ in range(k):
a,b = map(int, input().split())
mutexs[a-1].add(b-1)
mutexs[b-1].add(a-1)
def check(i,vst):
for v in vst:
if i in mutexs[v]:
return False
return True
res = 0
# 回溯枚举所有的组合
def backtrace(i,cur_value,cur_weight,vst):
if i >= n:
global res
res = max(res, cur_value)
return
backtrace(i+1,cur_value,cur_weight,vst)
if check(i,vst) and stocks[i][0] + cur_weight <= m:
vst.add(i)
backtrace(i+1, cur_value+stocks[i][1], cur_weight+stocks[i][0], vst)
vst.remove(i)
backtrace(0,0,0,set())
print(res)
题目描述
米小游是一位热爱冒险和收藏的小哥哥。最近,他迷上了购买各种精美的周边商品。不过,由于空间有限,米小游只能带一个容量为 m 的背包,背包只能装得下体积之和不超过 m 的商品。
商店里有 n 个商品,分别编号为 1 到 n,每个商品都有自己的价值 vali 和体积 wi。米小游希望在背包容量的限制下,尽可能地选择价值最高的商品。
然而,米小游面临一个难题:有些商品不能同时购买,因为它们会产生不好的化学反应。商店老板给米小游设定了 k 组互斥关系,每组关系由两个商品编号 a 和 b 组成,表示编号为 a 的商品和编号为 b 的商品不能同时购买。
米小游希望能够找到一种最佳的选择,使得他装入背包中的商品总价值最大。让我们帮米小游计算一下,如何在满足背包容量和互斥关系的情况下,获得最大价值的商品组合。
输入格式
第一行输入三个整数 n,m,k,分别表示商品数量、背包容量和互斥关系数量。
接下来 n 行,每行两个整数 wi,vi,分别表示每个物品的体积和价值。
接下来 k 行,每行输入两个整数 a,b,描述一组互斥关系。
输出格式
一行一个整数表示答案。
3 100 2
15 19
20 30
15 19
1 2
2 3
38
范围
对于 100% 的数据,满足 1≤n≤15,1≤m≤109,0≤k≤15,1≤wi,vi≤109,1≤a,b≤n,a=b。