UVA10817:Headmaster's Headache(状压dp)

来源:互联网 发布:六爻排盘软件哪个好 编辑:程序博客网 时间:2024/06/07 06:07


题意:s个学科,每个学科至少要2个老师教,现有m个老师,不能辞退他们的前提下,从n个应聘者招收若干个使得每个学科至少2个老师教,求总工资的最小值。

思路:dp[i][j]中的i表示科目被选的状态,j表示多于1个人选择某科目的状态,dp[(1<<s)-1][(1<<s)-1]即为答案。

# include <bits/stdc++.h># define INF 0x3f3f3f3fusing namespace std;int dp[1<<8][1<<8], sta[101], cost[101], num[10], sta1, sta2, sum, s, m, n, tmp;;int solve(){    int up = (1<<s)-1;    memset(dp, INF, sizeof(dp));    dp[sta1][sta2] = sum;    for(int i=0; i<n; ++i)        for(int j=up; j>=0; --j)            for(int k=up; k>=0; --k)            {                if(dp[j][k] == INF) continue;                int nsta1 = (j|sta[i]);                int nsta2 = (j&sta[i])|k;                dp[nsta1][nsta2] = min(dp[nsta1][nsta2], dp[j][k] + cost[i]);            }    return dp[up][up];}int main(){    char str[100];    while(~scanf("%d%d%d",&s,&m,&n)&&s)    {        memset(sta, 0, sizeof(sta));        memset(cost, 0, sizeof(cost));        memset(num, 0, sizeof(num));        sta1 = sta2 = sum = 0;        while(m--)        {            scanf("%d",&tmp);            gets(str);            int len = strlen(str);            for(int i=0; i<len; ++i)                if(isdigit(str[i]))                {                    int no = str[i]-'0';                    sta1 |= 1<<(no-1);                    ++num[no-1];                }            sum += tmp;        }        for(int i=0; i<s; ++i)            if(num[i] >= 2)                sta2 |= (1<<i);        for(int i=0; i<n; ++i)        {            scanf("%d",&cost[i]);            gets(str);            int len = strlen(str);            for(int j=0; j<len; ++j)                if(isdigit(str[j]))                {                    int no = str[j]-'0';                    sta[i] |= 1<<(no-1);                }        }        printf("%d\n",solve());    }    return 0;}





0 0
原创粉丝点击