zoukankan      html  css  js  c++  java
  • Codeforces Round #321 (Div. 2) Kefa and Dishes 状压+spfa

    原题链接:http://codeforces.com/contest/580/problem/D

    题意:

    给你一些一个有向图,求不超过m步的情况下,能获得的最大权值和是多少,点不能重复走。

    题解:

    令$dp[u][s]$为在节点u的时候状态是s的最大值。利用spfa的松弛操作来转移。

    代码:

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #define MAX_S 1<<19
    #define MAX_N 22
    using namespace std;
    
    typedef long long ll;
    
    struct edge {
    public:
        int to;
        ll cost;
    
        edge(int t, ll c) : to(t), cost(c) { }
    
        edge() { }
    };
    
    vector<edge> G[MAX_N];
    ll g[MAX_N][MAX_N];
    ll a[MAX_N];
    int n,m,k;
    
    int ones[MAX_S];
    
    ll dp[MAX_N][MAX_S];
    
    struct node {
    public:
        ll s;
        int u;
    
        node(ll ss, int uu) : s(ss), u(uu) { }
    
        node() { }
    };
    
    queue<node> que;
    bool inQue[MAX_N][MAX_S];
    
    int main() {
        cin.sync_with_stdio(false);
        cin >> n >> m >> k;
        for (int i = 0; i < (1 << n); i++) {
            int x = i;
            while (x)ones[i] += (x & 1), x >>= 1;
        }
        for (int i = 0; i < n; i++)
            cin >> a[i];
        for (int i = 0; i < k; i++) {
            int x, y;
            ll c;
            cin >> x >> y >> c;
            x--, y--;
            g[y][x] = c;
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                G[i].push_back(edge(j, g[i][j]));
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            dp[i][1 << i] = a[i];
            que.push(node(1 << i, i));
            inQue[i][1 << i] = 1;
        }
        while (!que.empty()) {
            node now = que.front();
            que.pop();
            ll s = now.s;
            int u = now.u;
            inQue[u][s] = 0;
            for (int i = 0; i < G[u].size(); i++) {
                int v = G[u][i].to;
                ll c = G[u][i].cost;
                if (s & (1 << v))continue;
                ll ns = s | (1 << v);
                if (ones[ns] > m)continue;
                if (dp[v][ns] < dp[u][s] + a[v] + c) {
                    dp[v][ns] = dp[u][s] + a[v] + c;
                    que.push(node(ns, v));
                    inQue[v][ns] = 1;
                }
            }
        }
        for (int i = 0; i < n; i++)
            for (int s = 0; s < (1 << n); s++)
                if (ones[s] == m)
                    ans = max(ans, dp[i][s]);
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    2016.11.21随笔
    2016.11.19随笔
    年月日
    导航position:absolute
    360搜索(边框)
    导航代码position:relative
    邮箱注册代码
    2016.11.18随笔
    2016.11.17随笔
    个人简历网页版代码
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4831101.html
Copyright © 2011-2022 走看看