[Algo] 状压dp
1. 我能赢吗
// 1. 我能赢吗
// https://leetcode.cn/problems/can-i-win/
bool func1(int n, int status, int rest, vector<int>& dp) {
if (rest <= 0) return false;
if (dp[status] != 0) return dp[status] == 1;
bool ans = false;
for (int i = 1; i <= n; i++) {
if (status & (1 << i) && !func1(n, status ^ (1 << i), rest - i, dp)) {
ans = true;
break;
}
}
dp[status] = ans == true ? 1 : -1;
return ans;
}
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= 0) return true;
int n = maxChoosableInteger;
if ((1 + n) * n / 2 < desiredTotal) return false;
int status = (1 << (n + 1)) - 1;
vector<int> dp(status + 1);
return func1(n, status, desiredTotal, dp);
}
2. 火柴拼正方形
// 2. 火柴拼正方形
// https://leetcode.cn/problems/matchsticks-to-square/
bool func2(vector<int>& matchsticks, int limit, int status, int cur, int rest, vector<int>& dp) {
// cur: 当前边的长度, rest: 剩余边数(包括当前边)
if (rest == 0) return status == 0;
if (dp[status] != 0) return dp[status] == 1;
int n = matchsticks.size();
bool ans = false;
for (int i = 0; i < n; i++) {
if (status & (1 << i) && cur + matchsticks[i] <= limit) {
if (cur + matchsticks[i] < limit) {
ans = func2(matchsticks, limit, status ^ (1 << i), cur + matchsticks[i], rest, dp);
}
else ans = func2(matchsticks, limit, status ^ (1 << i), 0, rest - 1, dp);
if (ans) break;
}
}
dp[status] = ans == true ? 1 : -1;
return ans;
}
bool makesquare(vector<int>& matchsticks) {
int n = matchsticks.size(), sum = 0;
for (int e : matchsticks) sum += e;
if (sum % 4 != 0) return false;
int status = (1 << n) - 1;
vector<int> dp(status + 1);
return func2(matchsticks, sum / 4, status, 0, 4, dp);
}
3. TSP问题
// 3. TSP问题
// https://www.luogu.com.cn/problem/P1171
int func3(vector<vector<int>>& graph, int status, int cur, vector<vector<int>>& dp) {
int n = graph.size();
if (status == (1 << n) - 1) return graph[cur][0];
if (dp[status][cur] != 0) return dp[status][cur];
int ans = INT32_MAX;
for (int i = 1; i < n; i++) {
if ((status & (1 << i)) == 0) {
ans = min(ans, func3(graph, status | (1 << i), i, dp) + graph[cur][i]);
}
}
dp[status][cur] = ans;
return ans;
}
int minDistance(vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<int>> dp(1 << n, vector<int>(n));
return func3(graph, 1, 0, dp);
}