Uva10817

9 篇文章 0 订阅
4 篇文章 0 订阅

题目链接

s0表示哪些科目没有一个老师教,s1表示是哪些科目只有一个老师教,s2表示有哪些科目有两个老师教,d(i,s1,s2)表示考虑钱i个时的最小花费,状态转移方程d(i,s1,s2)=min{d(i+1,s1′,s2′)+c[i],d(i+1,s1,s2)} 【c[i]表示聘用这个老师的花费,s1′和s2′表示招聘这个老师后更新的新状态′
第一项表示聘用,第二项不聘用,只有i>m才出现第二项,因为在职教师不能够辞退。
#include <iostream>
#include <cstdio>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 130;
const int INF = 1 << 20;
int s, m, n, x;
int d[maxn][1 << 8][1 << 8];
int c[maxn], st[maxn];

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;//在没有老师教的科目中求职者能教的课程
    int m1 = st[i] & s1;//在只有一个老师教的科目中求职者能教的课程
    s0 ^= m0; 
    s1 = (s1^m1) | m0;
    s2 |= m1;
    ans = min(ans, c[i] + dp(i + 1, s0, s1, s2));
    return ans;
}

int main()
{
    string str;
    while (getline(cin, str))
    {
        memset(st, 0, sizeof(st));
        stringstream ss(str);
        ss >> s >> m >> n;
        if (s == 0)
            break;
        for (int i = 0; i < m + n; i++)
        {
            getline(cin, str);
            stringstream ss(str);
            ss >> c[i];
            while (ss >> x)
            {
                st[i] |= 1 << (x - 1);//老师所能教的科目
            }
        }
        memset(d, -1, sizeof(d));
        cout << dp(0, (1 << s) - 1, 0, 0) << endl;//(1 << s) - 1表示一开始所有的课程都没有老师教
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值