zoukankan      html  css  js  c++  java
  • UVA10817-Headmaster's Headache(动态规划基础)

    Problem UVA10817-Headmaster's Headache

    Time Limit: 4500 mSec

    Problem Description

    Input

    The input consists of several test cases. The format of each of them is explained below: The first line contains three positive integers S, M and N. S (≤ 8) is the number of subjects, M( ≤ 20) is the number of serving teachers, and N (≤ 100) is the number of applicants. Each of the following M lines describes a serving teacher. It first gives the cost of employing him/her (10000 ≤ C ≤ 50000), followed by a list of subjects that he/she can teach. The subjects are numbered from 1 to S. You must keep on employing all of them. After that there are N lines, giving the details of the applicants in the same format. Input is terminated by a null case where S = 0. This case should not be processed.

     Output

    For each test case, give the minimum cost to employ the teachers under the constraints.
     

     Sample Input

    2 2 2
    10000 1
    20000 2
    30000 1 2
    40000 1 2
    0 0 0
     

    Sample Output

    60000

    题解:状压dp,但是比较麻烦的地方在于不少于2人,因此最直接的想法就是三进制枚举,不过三进制写起来有些麻烦,转念一想,其实可以用两个二进制位来代替这个三进制,我的两个二进制位的状态定义其实有些问题,比较正的思路就是前八位和后八位分别代表一个和大于等于两个。我的代码是跟着lrj的思路做的,实现的思路还是很好的,三进制可以转成两个二进制,用两个集合来表示整个状态,很值得学习(好写嘛),状态定义为dp[i][s1][s2],表示考虑到前i个人,在状态(s1,s2)之下到达目标状态还要花费多少。这样方程就很好写了。在转移状态的时候需要位运算,这个硬想是很困难的,画个图就很简单了,交,并,对称差分别对应&,|,^。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxs = 10, maxm = 25, maxn = 105;
     6 const int INF = 1e9;
     7 
     8 int s, m, n;
     9 int cost[maxn + maxm], teach[maxn + maxm];
    10 int dp[maxm + maxn][1 << maxs][1 << maxs];
    11 
    12 int DP(int i, int s0, int s1, int s2) {
    13     if (i == m + n) return s2 == (1 << s) - 1 ? 0 : INF;
    14     int& ans = dp[i][s1][s2];
    15     if (ans >= 0) return ans;
    16 
    17     ans = INF;
    18     if (i >= m) ans = DP(i + 1, s0, s1, s2);
    19 
    20     int t0 = s0 & teach[i];        //new subjects
    21     int t1 = s1 & teach[i];
    22     s0 ^= t0; s1 = (s1^t1) | t0; s2 |= t1;
    23     ans = min(ans, DP(i + 1, s0, s1, s2) + cost[i]);
    24     return ans;
    25 }
    26 
    27 int main()
    28 {
    29     //freopen("input.txt", "r", stdin);
    30     string str;
    31     while (getline(cin, str)) {
    32         stringstream ss(str);
    33         ss >> s >> m >> n;
    34         if (s == 0) break;
    35         memset(teach, 0, sizeof(teach));
    36         memset(dp, -1, sizeof(dp));
    37         for (int i = 0; i < n + m; i++) {
    38             getline(cin, str);
    39             stringstream ss(str);
    40             ss >> cost[i];
    41             int t;
    42             while (ss >> t) {
    43                 t--;
    44                 teach[i] |= (1 << t);
    45             }
    46         }
    47         printf("%d
    ", DP(0, (1 << s) - 1, 0, 0));
    48     }
    49     return 0;
    50 }
  • 相关阅读:
    JavaScript return语句 【每日一段代码53】
    JavaScript continue【每日一段代码60】
    JavaScript for 循环【每日一段代码55】
    JavaScript 带有参数并返回值【每日一段代码54】
    JavaScript for 循环标题【每日一段代码56】
    JavaScript 确认按钮 【每日一段代码48】
    JavaScript 参数调用 【每日一段代码51】
    JavaScript while 循环【每日一段代码57】
    SRM 548 DIV2
    POJ 1131 Doing Windows
  • 原文地址:https://www.cnblogs.com/npugen/p/9817555.html
Copyright © 2011-2022 走看看