UVA10817 Headmaster‘s Headache

本文介绍了一种使用动态规划解决教育问题的方法,涉及m位老师和n位求职者教授s个科目,目标是确保每个科目至少有两人教学,同时求解最少费用。通过二进制表示科目状态,展示了如何利用状压dp算法来计算最优化的教师分配方案。
摘要由CSDN通过智能技术生成

题目大意:
有m个老师与n个求职者还有s个科目
老师必须选,求职者可选可不选
要求这s个科目都要有至少两个人教
问你最少花费是多少

思路:
状压dp
我们可以设s1用二进制表示目前恰好有一个人教的科目
s2表示有两个人教的科目
s0表示目前没有人教的科目
面对老师的时候把他的花费跟他教的科目都放进来
而求职者的时候就有两种状态了
直接跳到下一个人不选或者选他加入他的花费
主要还是二进制方面表示状态的东西可能比较难想
具体看代码

#include <bits/stdc++.h>

using namespace std;
const int N=(1<<8)+9;
int c[300];
int st[300];//用二进制表示这个人能教的科目是啥
int d[130][N][N];
int s,m,n;
int dp(int i,int s0,int s1,int s2)
{
    if(i==m+n)return s2==(1<<s)-1?0:0x3f3f3f3f;//如果说两个人教的科目包括了全部科目的话就返回0说明是OK的
    int& ans=d[i][s1][s2];
    if(ans>=0)return ans;
    ans=0x3f3f3f3f;
    if(i>=m)ans=dp(i+1,s0,s1,s2);//如果是求职者就看一下不选他的情况
    int m0=st[i]&s0,m1=st[i]&s1;//m0表示目前没有人教的科目中与这个人能教的科目的重叠部分,m1表示目前一个人教的科目中与这个人教的科目的重叠部分
    s0^=m0;//那就让这个人来教目前没有人教的科目
    s1=(s1^m1)|m0;//因为教了之后变两个人教的科目了要删掉之前教一个人的科目,同时加上没有人教的科目与这个人教的重叠部分
    s2^=m1;
    ans=min(ans,dp(i+1,s0,s1,s2)+c[i]);
    return ans;
}
int main()
{
    while(cin>>s>>m>>n&&s)
    {
        memset(st,0,sizeof(st));
        memset(d,-1,sizeof(d));
        for(int i=0; i<m+n; i++)
        {
            cin>>c[i];
            char ch;
            while((ch=getchar())!='\n')
            {
                st[i]|=(1<<(ch-'1'));
            }
        }
        cout<<dp(0,(1<<s)-1,0,0)<<endl;;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值