UVA - 10817 Headmaster's Headache
Posted D O Time
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA - 10817 Headmaster's Headache相关的知识,希望对你有一定的参考价值。
题目大意:有一些老师,每一位都有自己的工资以及教授的课程。共s<=8个课程。其中的一些老师必须选择,问你保证每节课至少有一个老师的最少总工资。
题解:
首先很容易想到状态压缩,搞一个3进制的数,分别表示每一门课程的情况,一共38=6561。但是这样是不行的,相当于暴力啊!
一个套路:三进制转化为二进制*2。也就是搞一个216的数,1~8和9~16表示每门课程,这样就可以利用位运算了。
然后知道这个就很显然的,一个背包问题。要注意,这样转化为二进制之后,要定义一条规则,每次添加课程,优先1~8位,有了就再加到9~16位即可。
处理出所有强制选择的老师的授课状态S,令dp[S]=sum{c[]}。其他的全是INF。然后从All=(1<<(s*2)-1到S。当成01背包做即可。
1 #include<queue> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define RG register 8 #define LL long long 9 #define fre(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout); 10 using namespace std; 11 const int MAXN=1000; 12 int s,n,m,S,sum,All; 13 int c[MAXN],a[MAXN],dp[1<<16]; 14 char ch; 15 int main() 16 { 17 while(scanf("%d%d%d",&s,&n,&m)!=EOF) 18 { 19 if(s==0)break; 20 All=(1<<(s*2))-1; 21 for(int i=1,flag,x;i<=n+m;i++)//鬼里鬼气的输入 22 { 23 a[i]=0; 24 scanf("%d",&c[i]); 25 flag=0; 26 while(1) 27 { 28 ch=getchar(); 29 while(ch<‘0‘||ch>‘9‘) 30 { 31 if(ch==‘\n‘||ch==‘\r‘) { flag=1; break; } 32 ch=getchar(); 33 } 34 if(flag)break; 35 x=0; 36 while(‘0‘<=ch&&ch<=‘9‘)x=x*10+(ch-‘0‘),ch=getchar(); 37 a[i]|=(1<<(x-1)); 38 if(ch==‘\n‘||ch==‘\r‘)break; 39 } 40 } 41 S=sum=0; 42 for(int i=1;i<=n;i++)//按照规则,优先填后面的 43 { 44 sum+=c[i]; 45 int p=S&a[i]; 46 S|=(p<<s); 47 S|=a[i]; 48 } 49 memset(dp,0x3f3f3f3f,sizeof dp); 50 dp[S]=sum; 51 for(int i=n+1;i<=n+m;i++) 52 { 53 for(int j=All;j>=S;j--)//按照规则,优先填后面的 54 { 55 int p=a[i]&j; 56 p=a[i]|(p<<s); 57 dp[j|p]=min(dp[j|p],dp[j]+c[i]); 58 } 59 } 60 printf("%d\n",dp[All]); 61 } 62 return 0; 63 }
以上是关于UVA - 10817 Headmaster's Headache的主要内容,如果未能解决你的问题,请参考以下文章
Headmaster's Headache UVa10817DP(缺)
UVA - 10817 Headmaster's Headache (状压dp+记忆化搜索)
(状压dp)uva 10817 Headmaster's Headache