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

题意:刘汝佳训练指南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 long
const 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 3
1000 1
1000 2
1000 3
1000 2
50000 1 5 7 3 4
50000 1 6 8
50000 1 2 3 4 5 6 7 8
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建校长信息表`HeadMaster`的SQL语句如下: ``` CREATE TABLE HeadMaster ( HeadID CHAR(4) NOT NULL, Head_Name CHAR(10) NOT NULL, S_ID CHAR(4) NOT NULL, App_Date DATETIME, CONSTRAINT PK_HeadMaster PRIMARY KEY (HeadID), CONSTRAINT FK_HeadMaster_S_ID FOREIGN KEY (S_ID) REFERENCES School(S_ID) ); ``` 其中,`HeadID`、`Head_Name`、`S_ID`、`App_Date`分别是校长信息表`HeadMaster`的列名,对应的中文列名分别是校长编号、姓名、学校编号、任职日期。数据类型和长度分别如题所述。`App_Date`列为校长的任职日期,使用了`Datetime`类型。 主键约束使用`PK_HeadMaster`名称进行命名,外键约束使用`FK_HeadMaster_S_ID`进行命名,对应`S_ID`列的外键关系。约束必须引用`School`表的`S_ID`列。 以上SQL语句创建了一个校长信息表`HeadMaster`,其中主键为`HeadID`列,`S_ID`列为`School`表的外键。 创建学校信息表`School`的SQL语句如下: ``` CREATE TABLE School ( S_ID CHAR(4) NOT NULL, S_Name VARCHAR(20) NOT NULL, s_add CHAR(20), CONSTRAINT PK_School PRIMARY KEY (S_ID) ); ``` 其中,`S_ID`、`S_Name`、`s_add`分别是学校信息表`School`的列名,对应的中文列名分别是学校编号、学校名称、学校地址。数据类型和长度分别如题所述。 主键约束使用`PK_School`名称进行命名。 以上SQL语句创建了一个学校信息表`School`,其中主键为`S_ID`列。 创建教师类型表`TeacherType`的SQL语句如下: ``` CREATE TABLE TeacherType ( TypeID CHAR(4) NOT NULL, TypeName CHAR(20) NOT NULL, CONSTRAINT PK_TeacherType PRIMARY KEY (TypeID) ); ``` 其中,`TypeID`、`TypeName`分别是教师类型表`TeacherType`的列名,对应的中文列名分别是类型编号、类型名称。数据类型和长度分别如题所述。 主键约束使用`PK_TeacherType`名称进行命名。 以上SQL语句创建了一个教师类型表`TeacherType`,其中主键为`TypeID`列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值