UVa 10817 Headmaster‘s Headache 【01背包 位运算】

来源:互联网 发布:作图软件app 编辑:程序博客网 时间:2024/06/04 00:07

题意:刘汝佳训练指南p95


题解:此题可以设dp[s2][s1] = 授课状态为s2、s1时的最小花费(s1为课程授课状态为1的集合,s2为授课状态为2的集合)

然后视招募的新老师为要装进背包里的物品,授课状态s2,s1为容量,最终答案就为dp[(1<<S)-1][(1<<S)-1](S为课程数目)

具体转移方程如下:

设s2,s1为招募该老师前的状态,ns2,ns1为招募该老师后的状态则,ns1 = s1 | s ,ns2 = s2 | (s1 & s) ,(s为该老师能教授的课程)

dp[ns2][ns1] = min(dp[s1 | s[i]][s2 | (s1 & s[i])]) + v[i],s[i]是第i个老师授课集合,v[i]是第i个老师的收费


#include<iostream>#include<stdio.h>#include<algorithm>#include<cmath>#include<stdlib.h>#include <string.h>#include<queue>#include<set>#include<map>#include<stack>#include<time.h>using namespace std;#define MAX_N 505#define inf 0x3f3f3f3f#define LL long long#define ull unsigned long longconst LL INF = 1e18;const int mod = 1e8+7;typedef pair<double, int>P;int S, M, N;int tC[25];int aC[105];int teacher[25];int applicant[105];int dp[1<<8][1<<8];int getT(){    char c;    int ans = 0;    int d;    c = getchar();    while(c!='\n') {        scanf("%d", &d);        d--;        ans |= (1<<d);        c = getchar();    }    return ans;}void init(){    memset(dp, inf, sizeof(dp));}int main(){    while(cin >> S >> M >> N && S+M+N) {        init();        int s1 = 0;        int s2 = 0;        int sum = 0;        for(int i=0; i<M; i++) {            scanf("%d", &tC[i]);            teacher[i] = getT();            sum += tC[i];            s2 |= (s1 & teacher[i]);            s1 |= teacher[i];        }        for(int i=0; i<N; i++) {            scanf("%d", &aC[i]);            applicant[i] = getT();        }        dp[s2][s1] = sum;        for(int k=0; k<N; k++) {            int s = applicant[k];            for(int i=(1<<S)-1; i>=0; i--) {                for(int j=(1<<S)-1; j>=0; j--) {                    int ns1 = j|s;                    int ns2 = i|(j&s);                    dp[ns2][ns1] = min(dp[ns2][ns1], dp[i][j]+aC[k]);                }            }        }        /*       for(int i=0; i<(1<<S); i++) {            for(int j=0; j<(1<<S); j++) {                if(dp[i][j] == inf)                    printf("0 ");                else                    printf("%d ",dp[i][j]);            }            puts("");        }*/        cout << dp[(1<<S)-1][(1<<S)-1] << endl;    }    return 0;}/*8 4 31000 11000 21000 31000 250000 1 5 7 3 450000 1 6 850000 1 2 3 4 5 6 7 8*/


0 0
原创粉丝点击