状压dp

[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);
}
posted @ 2025-03-25 15:53  yaoguyuan  阅读(10)  评论(0)    收藏  举报