UVA-10817 Headmaster's Headache

题目大意:

有s个学科,现在在学校有n个教师在教书,这些教师必须要被雇佣,现在还有m个教师正在应聘。现在给出这n个在职教师的工资和能教的科目,给出m个应聘教师的工资和能教的科目,现在希望这s个科目,每个都有至少两个教师教授,问你最少需要支付的工资是多少。

解题思路:

动态规划。状压DP。

dp[i]表示i这个状态需要支付的最少工资。因为每个科目至少两个教师,且最多只有8个科目,所以很明显状压DP。

设状态st,st有2*s有效位,低s位表示s个科目有一个教师,高s位也表示s个科目有一个教师。当2*s位都为1的时候表示最少能满足要求的状态。

设状态tt,表示第i个教师能教授科目的状态。

那么状态转移就可以写为:

dp[st | tt] = dp[st] + c[i]

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 105;
const int INF = 0x3f3f3f3f;
const int maxm = (1 << 16) + 10;

int s, m, n;
int tot, vis[10], tt[257];
int a[10], c[maxn], dp[maxm], ss[maxn][10];

bool judge(int a, int b) {
	while (b) {
		if ((b & 1) && !(a & 1)) return false;
		b >>= 1; a >>= 1;
	}
	return true;
}
void dfs(int p, int st, int j) {
	if (p == ss[j][0]) {
		tt[tot++] = st | (1 << (ss[j][p] - 1));
		tt[tot++] = st | (1 << (ss[j][p] - 1 + s));
		return;
	}

	dfs(p + 1, st | (1 << (ss[j][p] - 1)), j);
	dfs(p + 1, st | (1 << (ss[j][p] - 1 + s)), j);
}
int main() {
	while (~scanf("%d%d%d", &s, &m, &n) && s) {
		memset(a, 0, sizeof(a));
		int tmp, ans = 0; char op;
		for (int i = 0; i < m; ++i) {
			scanf("%d", &tmp); ans += tmp;
			while (scanf("%d%c", &tmp, &op) == 2) {
				++a[tmp - 1];
				if (op == '\n') break;
			}
		}
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &c[i]); int tmp, cnt = 0;
			memset(vis, 0, sizeof(vis));
			while (scanf("%d%c", &tmp, &op) == 2) {
				if (!vis[tmp]) { ss[i][++cnt] = tmp; vis[tmp] = 1; }
				if (op == '\n') break;
			}
			ss[i][0] = cnt;
		}

		int be = 0, st = (1 << (2 * s)) - 1;
		for (int i = 0; i < s; ++i) {
			if (!a[i]) continue;
			else if (a[i] == 1) be += (1 << (i + s));
			else if (a[i] >= 2) be += (1 << i) + (1 << (s + i));
		}

		memset(dp, 0x3f, sizeof(dp));
		dp[be] = 0;
		for (int j = 1; j <= n; ++j) {
			tot = 0;
			dfs(1, 0, j);
			
			for (int i = st; i >= be; --i) {
				if (!judge(i, be)) continue;
				for (int k = 0; k < tot; ++k) {
					if (i == (i | tt[k])) continue;
					dp[i | tt[k]] = min(dp[i | tt[k]], dp[i] + c[j]);
				}
			}
		}
		printf("%d\n", ans + dp[st]);
	}
	return 0;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值