UVA10817 - Headmaster's Headache

用集合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
#include
#include
#include
#include
#include
#include
#include 
#include 
using namespace std;

#define INF 1e9
#define maxn 9
int d[150][1<1<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<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<1, 0, 0) << endl;
    }
    return 0;
}

你可能感兴趣的:(UVA10817 - Headmaster's Headache)