UVA10817 - Headmaster's Headache

来源:互联网 发布:御膳房算法平台 编辑:程序博客网 时间:2024/06/07 02:19

用集合s1表示一个人教的科目的集合,s2表示至少两个人教的科目的集合,s0表示无人教的科目的集合.d(i, s1, s2)表示已经考虑了前i个人时的最小花费.
状态转移方程: d(i, s1, s2) = min(d(i+1, s1, s2), c[i] + d(i+1, s1’, s2’)), s1’, s2’表示招聘了第i个人后的新值。

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#include<vector>#include <iostream>#include <sstream>using namespace std;#define INF 1e9#define maxn 9int d[150][1<<maxn][1<<maxn], s, m, n;int st[150], c[150];void Init(int k, int p){    string s;    for(int i = 0; i < p; i++)    {        ++k;        int t;        getline(cin, s);        stringstream ss(s);        ss >> t;        c[k] = t;        st[k] = 0;        while(ss >> t)        {            st[k] |= 1<<(t-1);        }    }}int dp(int i, int s0, int s1, int s2){    if(i == m+n)return s2 == (1<<s)-1 ? 0 : INF;    int &ans = d[i][s1][s2];    if(ans >= 0)        return ans;    ans = INF;    if(i >= m)ans = dp(i+1, s0, s1, s2);    int m0 = st[i] & s0, m1 = st[i] & s1;    s0 = s0 ^ m0, s1 = (s1 ^ m1) | m0, s2 |= m1;    ans = min(ans, c[i] + dp(i+1, s0, s1, s2));    return ans;}int main(){    //freopen("in.txt", "r", stdin);    while(cin >> s >> m >> n)    {        getchar();        if(!s && !m && !n)            break;        Init(-1, m);        Init(m-1, n);        memset(d, -1, sizeof(d));        cout << dp(0, (1<<s)-1, 0, 0) << endl;    }    return 0;}
0 0
原创粉丝点击