UVA 10817-Headmaster’s Headache(状态压缩DP)

题目大意:有S(S<=8)门课程,每门课程要求至少有2名老师教,雇佣每个老师需要一定的花费,每个老师可以教一门或多门课程。现有M(M<=20)名在职老师,N(N<=100)名应聘者,对于在职老师,必须每个都雇佣,求在满足每门课程至少2个老师教的情况下最少的花费是多少。

用d[i][j]表示前i名老师状态为j的情况下最少的花费,j是S位三进制数,对于每一位三进制位u,为0时表示课程u当前没有老师教,为1表示课程u当前有一名老师教,为2表示课程u当前有两名老师教。最终答案为d[N][3^S-1]。

计算d[i][j]时,考虑是否雇佣第i位老师完成状态转移,如果雇佣,那么尽量充分利用这个老师所教的课程,对于这个老师教的每一门课,如果当前的j的那一门课对应三进制位大于0,那么减1,否则不变。

状态转移方程:d[i][j]=max { d[i-1][j],d[i-1][v]+cost[i] }(v为将可以减去的课程减去之后的状态)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char a[300];
int b[105][10];
int c[10];
int d[105][7300];
int co[105];
int basethre[7100][10];
int basetco[10];
int main(void)
{
	int i,j,u,m,n,p,q,lo,sum,sump,minp,OK;
	q=1;
	for(i=1;i<=8;i++)
	{
		basetco[i]=q;
		q=q*3;
	}
	for(i=0;i<q;i++)
	{
		p=i;
		for(j=1;j<=8;j++)
		{
			u=p%3;
			basethre[i][j]=u;
			p=p/3;
			if(p==0)
			{
				break;
			}
		}
	}
	scanf("%d%d%d",&p,&n,&m);
	getchar();
	while((n!=0)||(p!=0)||(m!=0))
	{
		q=1;
		for(i=1;i<=p;i++)
		{
			q=q*3;
		}
		q--;
		sum=0;
		for(i=1;i<=n;i++)
		{
			gets(a);
			lo=strlen(a);
			for(j=0;j<lo;j++)
			{
				if((a[j]>='0')&&(a[j]<='9'))
				{
					sump=0;
					while((a[j]>='0')&&(a[j]<='9'))
					{
						sump=sump*10+a[j]-'0';
						j++;
					}
					sum=sum+sump;
					break;
				}
			}
			for(u=j;u<lo;u++)
			{
				if((a[u]>='0')&&(a[u]<='9')&&(c[a[u]-'0']<2))
				{
					c[a[u]-'0']++;
				}
			}
		}
		for(i=1;i<=m;i++)
		{
			gets(a);
			lo=strlen(a);
			for(j=0;j<lo;j++)
			{
				if((a[j]>='0')&&(a[j]<='9'))
				{
					sump=0;
					while((a[j]>='0')&&(a[j]<='9'))
					{
						sump=sump*10+a[j]-'0';
						j++;
					}
					co[i]=sump;
					break;
				}
			}
			for(u=j;u<lo;u++)
			{
				if((a[u]>='0')&&(a[u]<='9'))
				{
					b[i][a[u]-'0']=1;
				}
			}
		}
		d[0][0]=sum;
		for(j=1;j<=q;j++)
		{
			OK=1;
			for(u=1;u<=p;u++)
			{
				if(basethre[j][u]>c[u])
				{
					OK=0;
					break;
				}
			}
			if(OK==1)
			{
				d[0][j]=sum;
			}
			else
			{
				d[0][j]=1000000000;
			}
		}
		for(i=1;i<=m;i++)
		{
			d[i][0]=sum;
			for(j=1;j<=q;j++)
			{
				minp=d[i-1][j];
				sump=0;
				for(u=1;u<=p;u++)
				{
					if((basethre[j][u]>0)&&(b[i][u]==1))
					{
						sump=sump+basetco[u];
					}
				}
				if(minp>d[i-1][j-sump]+co[i])
				{
					minp=d[i-1][j-sump]+co[i];
				}
				d[i][j]=minp;
			}
		}
		printf("%d\n",d[m][q]);
		for(i=0;i<=10;i++)
		{
			c[i]=0;
		}
		memset(b,0,sizeof(b));
		scanf("%d%d%d",&p,&n,&m);
		getchar();
	}
	return 0;
}
时间: 2024-08-06 18:56:23

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

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 - 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 (状压类背包dp+三进制编码)

题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课程已经分别有几个人教”作为状态来进行转移,每个人能教的课程集合作为“物品重量”,工资作为“价值”来更新dp值,类似01背包,每放进一个人,从后往前更新即可. 状态的表示可以用三进制编码,为了写起来舒服,我写了个结构体作为状态和编码转换的桥梁,也可以进行状态的“加法运算”,虽然速度比较慢就是了~~ 有

(状压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

题目: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 11825 Hackers&#39; Crackdown(状态压缩DP)

Hackers' Crackdown Input: Standard Input Output: Standard Output   Miracle Corporations has a number of system services running in a distributed computer system which is a prime target for hackers. The system is basically a set of N computer nodes wi

UVA 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态). 求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务). 分析: 题目说白了.就

UVa 10651 Pebble Solitaire(状态压缩DP)

题意:转化为01序列,可以做如下转换011–>100, 110–>001 使得序列的1最少 二进制的集合表示: 空集:0 全集:( 1< #include<iostream> #include<algorithm> #include<map> #include<cstdio> #include<cstdlib> #include<vector> #include<cmath> #include<cs