zoukankan      html  css  js  c++  java
  • 【UVA10187】Headmaster's Headache(校长的烦恼)

    题面

    某个学校要师资力量不够,要招收新的老师,第一行给出s、m、n,现在在任的老师有m个,然后给出m行表示每个老师的信息,分别是该老师的工资,以及可教授的课程(个数不一定),然后在n行表示可招收的老师信息,同样是工资和课程,s表示该学校开售的课程,问,最少花多少钱可以使得该学校开设的s个课程每个课程有两个老师任教。
    m<=20,n<=100,s<=8

    分析

    这题好经典,紫书上的,记忆化搜索+状压dp,值得一学。
    我看到的比较喜欢的一种解法是用集合的运算。其实是三个集合,无人教集合s0,一人教集合s1,两人教集合s2.最后要从s0满,s1、s2空算出s0、s1空,s2满的答案。
    用dp[i][s0][s1][s2]表示计算到第i个人为止,三个集合状态为s0,s1,s2时的最小花费。然而知道了s1,s2可以计算出s0,所以为节省空间优化为dp[i][s1][s2]
    每次转移需要更新这三个集合,比如四门课,现在s0是1001,s1是0100,s2是0010,如果下一个老师可以教第2、4门课,即0101
    把新老师加入集合后,s0-->1000 s1-->0001 s2-->0110
    怎么得到的呢?用 m0表示他能教而且当前没有人教的课 ,m1表示他能教且当前只有一个人教的课 。
    则 m0=0101&1001=0001 m1=0100&0101=0100,而可以用m0和m1来更新s0,s1,s2.
    s0=s0^m0=1000 没有人教是1,有人教是0,而0001中1是可以教,0是不能教的,刚好相反,原来无人教的1遇到有人教的1会变成0,表示有人教。
    s1=(s1^m1)|m0=0001 s1第一部分与s0的更新同理,但是或了s0,表示从s0那儿升级上来有一人教的
    s2=s2|m1=0110  因为s2就只能从m1那儿升级上来了。

    分析

    #include<bits/stdc++.h>
    using namespace std;
    #define N 200
    #define INF 1234567890
    int s,n,m,x,mx;
    int w[N],can[N],dp[N][1<<8][1<<8];
    
    inline int dfs(int i,int s0,int s1,int s2)
    {
        if(i==n+m+1) return s2==mx?0:INF;
        int &ans=dp[i][s1][s2];
        if(ans>=0)return ans;
        ans=INF;
        if(i>n)ans=dfs(i+1,s0,s1,s2);
        int m0=s0&can[i],m1=s1&can[i];
        s0^=m0,s1=(s1^m1)|m0,s2|=m1;
        ans=min(ans,w[i]+dfs(i+1,s0,s1,s2));
        return ans;
    }
    
    inline void init()
    {
        mx=(1<<s)-1;
        memset(dp,-1,sizeof(dp));
        memset(can,0,sizeof(can));
    }
    
    int main()
    {
        while(scanf("%d%d%d",&s,&n,&m)&&s)
        {
            init();
            for(int i=1;i<=n+m;i++)
            {
                scanf("%d",&w[i]);
                while(1)
                {
                    scanf("%d",&x);
                    can[i]=can[i]|(1<<x-1);
                    char c=getchar();
                    if(c=='
    ')break;
                }
            }
            int ans=dfs(0,mx,0,0);
            printf("%d
    ",ans);
        }
    }
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    [考试反思]0904NOIP模拟测试37:守望
    游戏:最短路,拆点
    [考试反思]0903NOIP模拟测试36:复始
    [考试反思]0902NOIP模拟测试35:摆动
    长寿花:dp
    [考试反思]0901NOIP模拟测试34:游离
    赤壁情:dp
    [考试反思]0829NOIP模拟测试33:仰望
    [考试反思]0828NOIP模拟测试32:沉底
    宅男计划:单峰函数三分
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9790348.html
Copyright © 2011-2022 走看看