zoukankan      html  css  js  c++  java
  • Codeforces Gym 100676G Training Camp 状压dp

    http://codeforces.com/gym/100676

    题目大意是告诉你要修n门课,每门课有一个权值w[i], 在第k天修该课程讲获得k*w[i]的学习点数,给出了课程与先修课程的关系,要修该课程必须修完先修课程。问最多能学到多少点数。

    非常简单的一道状压dp(一开始我还误导队友写成两维的去了 T^T);

    dp[s] : s 的二进制存放的是已经选择的课程,在该状态下的能获得的最大的点数。

    这时如果再学一门课程k,将转移到状态ss (s | (1 << k) ) ,能否转移需要判断合法性。这里把课程k的先修课程存在一个int里面,S & prev[k] == prev[k]则表示可以选项k课程。dp数组一开始需要初始化成无穷小。最后只要找dp[(1 << n ) - 1] 。

    /*输入真恶心*/

    #include <map>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int INF = 999999999;
    
    int n,m;
    
    map<string, int> Map;
    
    int w[20];
    
    int prve[20];
    
    void read() {
        cin >> n >> m;getchar();
    
        char _a[101];
        string _s, _t;
        int _num;
        int _len;
        for (int i=0; i<n; i++) {
            gets(_a);
    
            _len = strlen(_a);
    
            int k = 0;
            while(_a[k] < '0' || _a[k] > '9') k++;
    
            _a[k-1] = '';
            _s = (string) _a;
    
            _num = 0;
            while (k < _len && _a[k] >= '0' && _a[k] <= '9') {
                _num = _num * 10 + _a[k] - '0';
                k++;
            }
    
            Map[_s] = i;
            w[i] = _num;
        }
    
        for (int i=0; i<m; i++) {
            gets(_a);
    
            int k = 0;
            while (_a[k] != '-') k++;
    
            _a[k-1] = '';
    
            _s = (string) _a;
            _t = (string) (_a + k + 4);
    
            prve[Map[_t]] |= (1 << Map[_s]);
        }
    }
    
    
    int dp[(1<<18)+5];
    
    void DP () {
    
        for (int s=0; s<(1<<n); s++) {
    
            int _num = 0;
    
            for (int i=0; i<n; i++) {
                _num += ((s >> i) & 1);
            }
    
            for (int i=0; i<n; i++) {
                int ss = s | (1 << i);
    
                if (((s >> i & 1) != 0) || ((s & prve[i]) != prve[i])) continue;
    
                if (_num == 0 && prve[i] == 0) {
                    dp[ss] = w[i];
                    continue;
                }
    
                dp[ss] = max(dp[ss], dp[s] + (_num + 1) * w[i]);
            }
        }
    
        cout << dp[(1<<n)-1] << endl;
    }
    
    void init() {
        Map.clear();
        fill(dp, dp + (1 << 18), -INF);
        memset(prve, 0, sizeof(prve));
    }
    
    int main () {
        int t;
        cin >> t ;
        while (t--) {
            init();
            read();
            DP();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    XmlDocument 操作 xml
    流模型 操作 xml
    对DataTable进行分组
    xml文件,xml格式字符串 读写
    Jquery中的checkbox 及radio的问题
    简单爬虫获取网页图片
    页面JS实现按钮点击增加输入框
    Log4j配置文件解读和模板页收藏
    JS异步传递数组Action接受的实现与疑惑
    博客园美化手记——CSS Javascript Html
  • 原文地址:https://www.cnblogs.com/xuelanghu/p/4483206.html
Copyright © 2011-2022 走看看