zoukankan      html  css  js  c++  java
  • UVa 10817

    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758

    题意:

    某校有m个教师和n个求职者,需讲授s个课程(1≤s≤8,1≤m≤20,1≤n≤100)。
    已知每人的工资c(10000≤c≤50000)和能教的课程集合,要求支付最少的工资使得每门课都至少有两名教师能教。在职教师不能辞退。

    分析:

    用两个集合:s1表示恰好有一个人教的科目集合,s2表示至少有两个人教的科目集合,
    而d(i,s1,s2)表示已经考虑了第i个人及其之后所有人时的最小花费。
    注意,把所有人一起从0编号,则编号0~m-1是在职教师,m~n+m-1是应聘者。
    状态转移方程为d(i,s1,s2) = min{d(i+1, s1', s2')+c[i], d(i+1, s1, s2)},其中第一项表示“聘用”,第二项表示“不聘用”。
    当i≥m时状态转移方程才出现第二项。这里s1'和s2'分别表示“招聘第i个人之后s1和s2的新值”,具体计算方法见代码。
    下面代码中的can[i]表示第i个人能教的科目集合(注意输入中科目从1开始编号,而代码的其他部分中科目从0开始编号,
    因此输入时要转换一下)。下面的代码用到了一个技巧:记忆化搜索中有一个参数s0,表示目前还没有人教的科目集合。
    这个参数并不需要记忆(因为有了s1和s2就能算出s0),仅是为了编程的方便(详见s1'和s2'的计算方式)。
    最终结果是 dp(0, (1<s)-1, 0, 0),因为初始时所有科目都没有人教。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <sstream>
     4 using namespace std;
     5 
     6 const int UP = 20 + 100 + 5;
     7 const int INF = 1234567;
     8 int s, m, n, c[UP], can[UP], d[UP][1<<8][1<<8];
     9 
    10 int dp(int i, int s0, int s1, int s2){
    11     if(i == m + n) return s2 == (1<<s)-1 ? 0 : INF;
    12     int& res = d[i][s1][s2];
    13     if(res >= 0) return res;
    14     res = INF;
    15     if(i >= m) res = dp(i+1, s0, s1, s2);
    16     int m0 = can[i] & s0, m1 = can[i] & s1;
    17     s0 ^= m0;  s1 = (s1 ^ m1) | m0;  s2 |= m1;
    18     res = min(res, c[i] + dp(i+1, s0, s1, s2));
    19     return res;
    20 }
    21 
    22 int main(){
    23     int temp;
    24     char str[999];
    25     while(~scanf("%d%d%d
    ", &s, &m, &n) && s){
    26         memset(can, 0, sizeof(can));
    27         memset(d, -1, sizeof(d));
    28         for(int i = 0; i < m + n; i++){
    29             gets(str);
    30             stringstream ss(str);
    31             ss >> c[i];
    32             while(ss){
    33                 ss >> temp;
    34                 can[i] |= (1 << temp - 1);
    35             }
    36         }
    37         printf("%d
    ", dp(0, (1<<s)-1, 0, 0));
    38     }
    39     return 0;
    40 }
  • 相关阅读:
    sql round
    COJ1086 分组01背包
    POJ3624 (01背包)
    COJ1271 Brackets Sequence
    nacoskubernet集群安装(离线安装)
    docker离线安装及本地yum配置
    rediskubernet集群离线安装
    mysql修改密码
    harbor离线安装
    ansibletidb3.0安装(离线版)
  • 原文地址:https://www.cnblogs.com/hkxy125/p/8739941.html
Copyright © 2011-2022 走看看