UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)

题目链接

题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教。在职教师必须选。

可以把“每个课程已经分别有几个人教”作为状态来进行转移,每个人能教的课程集合作为“物品重量”,工资作为“价值”来更新dp值,类似01背包,每放进一个人,从后往前更新即可。

状态的表示可以用三进制编码,为了写起来舒服,我写了个结构体作为状态和编码转换的桥梁,也可以进行状态的“加法运算”,虽然速度比较慢就是了~~

有点想吐槽的是,出题人就不能把每个人能教的课程数量也放在输入里么?非逼得人家用getline嘛~~

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll N=8+2,inf=0x3f3f3f3f;
 5 int k,n,m,d[(1<<(N*2))+10],co,mx;
 6 string line;
 7 struct D {
 8     int a[N];
 9     int& operator[](int x) {return a[x];}
10     D(int x=0) {
11         memset(a,0,sizeof a);
12         for(int i=0; i<k; ++i,x/=3)a[i]=x%3;
13     }
14     D operator+(D& b) {
15         D ret;
16         for(int i=0; i<k; ++i)ret[i]=min(a[i]+b[i],2);
17         return ret;
18     }
19     operator int() {
20         int ret=0;
21         for(int i=k-1; i>=0; --i)ret=ret*3+a[i];
22         return ret;
23     }
24
25 };
26
27 int main() {
28     ios::sync_with_stdio(0);
29     while(cin>>k>>n>>m&&k) {
30         cin.ignore();
31         memset(d,inf,sizeof d);
32         d[0]=0;
33         co=0,mx=pow(3,k)+0.5;
34         while(n--) {
35             getline(cin,line);
36             stringstream ss(line);
37             int x;
38             ss>>x;
39             co+=x;
40             D t;
41             while(ss>>x)t[x-1]=1;
42             for(int i=mx-1; i>=0; --i)if(!d[i])d[D(i)+t]=0;
43         }
44         for(int i=0; i<mx; ++i)if(!d[i])d[i]=co;
45         while(m--) {
46             getline(cin,line);
47             stringstream ss(line);
48             ss>>co;
49             int x;
50             D t;
51             while(ss>>x)t[x-1]=1;
52             for(int i=mx-1; i>=0; --i) {
53                 d[D(i)+t]=min(d[D(i)+t],d[i]+co);
54             }
55         }
56         printf("%d\n",d[mx-1]);
57     }
58     return 0;
59 }

UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)

原文地址:https://www.cnblogs.com/asdfsag/p/10380979.html

时间: 2024-10-24 00:51:40

UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)的相关文章

UVA 10817 Headmaster&#39;s Headache 状压DP

记录两个状态S1,S2分别记录哪些课程被1个人教过或2个人教过,然后记忆化搜索 UVA - 10817 Headmaster's Headache Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spr

(状压dp)uva 10817 Headmaster&#39;s Headache

题目地址 1 #include <bits/stdc++.h> 2 typedef long long ll; 3 using namespace std; 4 const int MAX=1e5+5; 5 const int INF=1e9; 6 int s,m,n; 7 int cost[125]; 8 //char sta[MAX]; 9 string sta; 10 int able[125]; 11 int dp[125][1<<8][1<<8]; 12 in

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

状压DP UVA 10817 Headmaster&#39;s Headache

题目传送门 1 /* 2 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 3 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s1二进制表示下至少有1位老师的科目集合 4 s2表示至少有2位老师的科目集合所花费的最小金额,状态转移方程(01):dp[t1][t2]=min(dp[t1][t2],dp[j][k]+c[i]); 5 j,k为当前两个集合,t1,t2为转移后的集合,另外求t1,t2用到了& |位运算

UVA 10817 - Headmaster&#39;s Headache

题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&page=show_problem&problem=1758 状态压缩的DP,dp[i][st]表示状态为st考虑后面i个人所有人最小花费, 因为每个科目有三种状态,可以用一个三进制数表示, 状态不是很多,所以可以把预先把每个数的三进制预处理出来, 决策为选和不选. #include<bits/std

Uva 10817 Headmaster&#39;s Headache (DP+ 状态压缩)

Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spring Field School is considering employing some new teachers for certain subjects. There are a number of teachers applying for the posts. Each teacher is able to teach one or

【UVa】Headmaster&#39;s Headache(状压dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758 晕....状压没考虑循环方向然后错了好久.. 这点要注意...(其实就是01背包变成了完全背包QAQ 我们将课程拆成两个点,然后状压 那么答案就是(1<<(s<<1))-1 转移就不说了,,,,,太简单.. #include <cstdio> #in

10817 - Headmaster&#39;s Headache(校长的烦恼)

经典的状态压缩DP . 根据DP的阶段定义,我们需要枚举每一个教师进行递推,但是由于每个教师可以教授的课程是复杂多样的,所以使得状态变得难以转移 .那么要怎么样表示状态呢? 显然增加一两个维度是无法胜任的,所以我们可以用二进制枚举子集的方法,用一个整数通过位运算充当一个集合 . C++提供的位运算符极像对集合的操作,我们恰好可以利用这一点 . 用d[i][s1][s2]表示考虑了前i个人时的最小花费 . 其中s1表示恰有一个人教的科目集合,s2表示至少有两个人教的科目集合 .因为由这两个量就可以

uva 11825 Hackers&#39; Crackdown (状压dp,子集枚举)

题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有相同的n种服务),对每台计算机,你可以选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让更多的服务瘫痪(没有计算机有该项服务). 思路:(见大白70页,我的方程与大白不同) 把n个集合P1.P2.Pn分成尽量多的组,使得每组中所有集合的并集等于全集,这里的集合Pi是计算机i及其相邻计算机的集合,用cover[i]表示若干Pi的集合S中所有集合的并集,dp[s]表示子集s最多可以分成多少组,则 如果cove