• UVa 10817 Headmaster's Headache(状态压缩DP)


    题意:

    有一个学校想要聘请老师,要求每个学科都有两个以上的老师授课,并且要使总费用最小。有S(最多8个)个学科,现任的M(最多20个)个老师(你必须继续聘请他们),N(最多100个)份申请。后来的M行每行有至少两个整数,表示现任的老师的工资,和他所教授的课程(可能不止一个)。再后来的N行每行有也有至少两个整数表示聘请这个老师所需的费用,以及他所教授的课程(可能不止一个)。

    思路:

    http://www.cnblogs.com/staginner/archive/2011/12/07/2278727.html

    如何进行状态压缩很关键,链接中的思路有待于细细琢磨。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <climits>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    const int MAXD = 10000;
    const int MAXN = 110;
    int s, m, n;
    int dp[MAXN][MAXD];
    int need[12], tech[MAXN][12], state[12];
    int cost[MAXN];
    
    void solve()
    {
        for (int i = 1; i <= s; ++i)
            need[i] = 2;
    
        char b[100];
        int v = 0;
        for (int i = 0; i < m; ++i)
        {
            gets(b);
            int k = strlen(b);
            int t;
            sscanf(b, "%d", &t);
            v += t;
    
            int j = 0;
            while (isdigit(b[j]))
                ++j;
    
            for (++j; j < k; ++j)
            {
                sscanf(&b[j], "%d", &t);
                if (need[t])
                    --need[t];
    
                while (isdigit(b[j]))
                    ++j;
            }
        }
    
        memset(tech, 0, sizeof(tech));
        for (int i = 1; i <= n; ++i)
        {
            gets(b);
            int k = strlen(b);
            int t;
            sscanf(b, "%d", &t);
            cost[i] = t;
    
            int j = 0;
            while (isdigit(b[j]))
                ++j;
    
            for (++j; j < k; ++j)
            {
                sscanf(&b[j], "%d", &t);
                tech[i][t] = 1;
    
                while (isdigit(b[j]))
                    ++j;
            }
        }
    
        memset(dp, 0x3f, sizeof(dp));
        int P = 0;
        for (int i = 1; i <= s; ++i)
            P = 3 * P + 2;
    
        for (int i = 0; i <= P; ++i)
        {
            int t = i;
            for (int j = 1; j <= s; ++j)
                state[j] = t % 3, t /= 3;
            int j;
            for (j = 1; j <= s && state[j] >= need[j]; ++j);
            if (j == s + 1)
                dp[0][i] = v;
        }
    
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 0; j <= P; ++j)
            {
                int t = j;
                for (int k = 1; k <= s; ++k)
                    state[k] = t % 3, t /= 3;
    
                for (int k = 1; k <= s; ++k)
                    if (tech[i][k] && state[k] < 2)
                        ++state[k];
    
                t = 0;
                for (int k = s; k >= 1; --k)
                    t = 3 * t + state[k];
    
                dp[i][j] = min(dp[i-1][j], dp[i-1][t] + cost[i]);
            }
        }
    }
    
    int main()
    {
        char b[100];
        while (gets(b))
        {
            sscanf(b, "%d %d %d", &s, &m, &n);
            if (!s)
                break;
            
            solve();
            printf("%d\n", dp[n][0]);
        }
    
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    Python之while循环
    Python之分支语句
    Python之变量
    Python开挂的吧!
    xshell 连接 ubuntu 16.04报错
    js中的script标签
    javascript中的事件学习总结
    【JAVAWEB学习笔记】04_JavaScript
    【JAVAWEB学习笔记】03_JavaScript
    【JAVAWEB学习笔记】02_HTML&CSS
  • 原文地址:https://www.cnblogs.com/kedebug/p/2788758.html
Copyright © 2020-2023  润新知