题目:https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests/
回溯DFS
- 路径要设成
全局变量
//官方题解
class Solution {
//delta表示每栋楼员工净变化量
//zero表示delta中0的个数
int[] delta;
int ans = 0, cnt = 0, zero, n;
public int maximumRequests(int n, int[][] requests) {
delta = new int[n];
zero = n;
this.n = n;
dfs(requests, 0);
return ans;
}
public void dfs(int[][] requests, int pos) {
//递归结束出口
//枚举完毕
if (pos == requests.length) {
//更新条件:所有楼的净变化量delta都为0
if (zero == n) {
//满足条件则更新答案
ans = Math.max(ans, cnt);
}
return;
}
//一、做选择
//有两种选择
//1.不选 requests[pos]
dfs(requests, pos + 1);
//2.选 requests[pos]
int z = zero; //为了之后能还原zero
//二、处理选择操作
++cnt;
int[] r = requests[pos];
int x = r[0], y = r[1];
//x离开,原来的delta[x]变化,zero怎么变
//2-1,zero不变
//1-0,zero++
//0-(-1),zero--
//可以离开前后各判断一次delta[x]===0
zero -= delta[x] == 0 ? 1 : 0;
--delta[x];
zero += delta[x] == 0 ? 1 : 0;
//到达y
zero -= delta[y] == 0 ? 1 : 0;
++delta[y];
zero += delta[y] == 0 ? 1 : 0;
//三、递归下一层选择
dfs(requests, pos + 1);
//四、撤销选择
//还原全局变量,因为要回溯到上一层,要似乎没有进入过下一层的选择一样
--delta[y];
++delta[x];
--cnt;
zero = z;
}
}
二进制枚举
思路
- 用二进制数mask表示所有的请求
- mask中1的个数表示已接受的请求数
- 枚举每个mask
- 剪枝:1的个数小于目前
最多可达成的换楼请求数目
,则continue
- 对于每个mask,
delta
都是独立的,皆初始化为0 - 循环
已接受的请求们
,更新delta - 更新答案 when 满足条件:delta所有值皆为0
//官方题解
class Solution {
public int maximumRequests(int n, int[][] requests) {
int[] delta = new int[n];
int ans = 0, m = requests.length;
for (int mask = 0; mask < (1 << m); ++mask) {
int cnt = Integer.bitCount(mask);
if (cnt <= ans) {
continue;
}
Arrays.fill(delta, 0);
for (int i = 0; i < m; ++i) {
if ((mask & (1 << i)) != 0) {
++delta[requests[i][0]];
--delta[requests[i][1]];
}
}
boolean flag = true;
for (int x : delta) {
if (x != 0) {
flag = false;
break;
}
}
if (flag) {
ans = cnt;
}
}
return ans;
}
}